Skip to content

Regression in typer for erikerlandson/coulomb #23610

@WojciechMazur

Description

@WojciechMazur

Based on OpenCB failure in erikerlandson/coulomb Open CB logs

Compiler version

Last good release: 3.7.3-RC1-bin-20250717-fb66af2-NIGHTLY
First bad release: 3.7.3-RC1-bin-20250718-42fdd76-NIGHTLY
Bisect points to 45f7ef6 / #23532

Minimized code

Not yet minimized, the issue arises in transparent inline macros used to calculate ouput types, the code is quite complex, reproducer:

//> using dep "com.manyangled::coulomb-units:0.9.0-RC1"
//> using dep "com.manyangled::coulomb-refined:0.9.0-RC1"

import eu.timepit.refined.*
import eu.timepit.refined.api.*
import eu.timepit.refined.numeric.*

import coulomb.*
import coulomb.syntax.*
import coulomb.integrations.refined.all.given
import coulomb.units.si.{*, given}

import algebra.instances.all.given

class RefinedQuantityAlgebraicSuite extends CoulombSuite:
    test("works") {
        val x = 2d.withRP[Positive].withUnit[Meter]
        val y = 3d.withRP[Positive].withUnit[Meter]
        val res = 6d.withRP[Positive]
        (x * y).assertQ[Refined[Double, Positive], Meter ^ 2](res)
    }
    test("fails when inlined") {
        (
          2d.withRP[Positive].withUnit[Meter] 
          * 3d.withRP[Positive].withUnit[Meter]
        ).assertQ[Refined[Double, Positive], Meter ^ 2]( 6d.withRP[Positive])
    }


abstract class CoulombSuite:
  def test(name: String)(body: => Any): Unit = ???
  
  extension [V](v: V)
    def withRP[P]: Refined[V, P] = ???
  
  extension [V, U](q: Quantity[V, U])
    inline def assertQ[VT, UT](vt: VT): Unit = ???

Partial minimization, missing macros available here https://github.com/erikerlandson/coulomb/blob/e415644f2953dedb6accf927e512358210ae3172/core/src/main/scala/coulomb/infra/meta.scala#L235

trait MultiplicativeSemigroup[T]

object refined:
  infix opaque type Refined[T, P] = T
  final type Positive = Greater[0]
  class Greater[N](n: N)
  
  given MultiplicativeSemigroup[Double Refined refined.Positive] = ???
  
object coulomb:
  final type Meter
  given BaseUnit[Meter, "meter", "m"] = ???
  
  abstract class NamedUnit[Name, Abbv]
  abstract class BaseUnit[U, Name, Abbv] extends NamedUnit[Name, Abbv]

  abstract class SimplifiedUnit[U]:
    type UO
  object SimplifiedUnit:
    import scala.quoted.*
    transparent inline given g_SimplifiedUnit[U]: SimplifiedUnit[U] =
        ${ simplifiedUnit[U] }

    class NC[U, UOp] extends SimplifiedUnit[U]:
        type UO = UOp

    private def simplifiedUnit[U](using Quotes, Type[U]): Expr[SimplifiedUnit[U]] = {
      import quotes.reflect.*
      macros.simplify(TypeRepr.of[U]).asType match
        case '[uo] => '{ new NC[U, uo] }
    }
  end SimplifiedUnit
  
  final type *[L, R]
  final type /[L, R]
  final type ^[B, E]
 
  opaque type Quantity[V, U] = V
  object Quantity:
    extension [V](v: V)
      inline def withUnit[U]: Quantity[V, U] = v
    extension [V, U, Q[V, U] <: Quantity[V, U]](q: Q[V, U])
      inline def *[UR](qr: Quantity[V, UR])(using alg: MultiplicativeSemigroup[V],  su: SimplifiedUnit[U * UR]): Quantity[V, su.UO] = ???

  object syntax:
    export Quantity.withUnit

Output

[error] ./example.test.scala:25:13
[error] Found:    coulomb.Quantity[Double Refined eu.timepit.refined.numeric.Positive,
[error]   coulomb.units.si.Meter]
[error] Required: coulomb.Quantity[Any, UR]
[error] 
[error] where:    UR is a type variable
[error]           * 3d.withRP[Positive].withUnit[Meter]
[error]             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expectation

Should compile

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions