Description
Regression found in Open Community Build for thoughtworksinc/binding.scala
build logs
Compiler version
Last good release: 3.4.0-RC1-bin-20230726-97677cc-NIGHTLY
First bad release: 3.4.0-RC1-bin-20230727-ac69c66-NIGHTLY
Works in 3.3.1
Affects Scala 3.3.2 LTS backports
Bisect was not accurate enough, the commit of bisect result failed with other errors when building compiler
Regression candidate commits:
ac69c66 (bad) Ondřej Lhoták : add test for issue #17997 affecting the global object initialization checker (#18141)
d903d35 Nicolas Stucki: Add regression test (#18287)
cb73f0b EnzeXing: Add test for modifying this to AndType
c04d2db Jędrzej Rochala: Update scala3-presentation-compiler to 39e349e (#18296)
989c55c (bad) Jan Chyb : Fix regression #17245: Overloaded methods with ClassTags (#18286)
4b67b34 (bad, other error) Nicolas Stucki : Set missing expansion span for copied inlined node (#18229)
182331b (good) Nicolas Stucki : Support polymorphic functions with erased parameters (#18293)
5625107 Nicolas Stucki: Support polymorphic functions with erased parameters
f22f9db (bad, other error) Julien Richard-Foy : Set missing expansion span for copied inlined node
101ce3a Jan Chyb: Fix regression with Overloaded methods returning Functions
f5313ae EnzeXing: add fix for issue #17997 affecting the global object initialization checker
96ca0b6 Ondrej Lhotak: add test for issue #17997 affecting the global object initialization checker
Minimized code
// main.scala
trait Binding[+A]:
def value: A = ???
object Binding:
inline def apply[A](inline a: A): Binding[A] = ???
final case class Constant[+A](override val value: A) extends Binding[A]
extension [A](inline binding: Binding[A])
transparent inline def bind: A = null.asInstanceOf[A]
trait Vars[A] extends BindingSeq[A]
trait BindingSeq[+A]:
def foreachBinding[U](f: A => Binding[U]): Binding[Unit] = ???
extension [A](inline bindingSeq: BindingSeq[A])
transparent inline def foreach[U](inline f: A => U): Unit = ${ Macros.foreach('bindingSeq, 'f) }
@main def Test = {
val vars: Vars[Int] = ???
val works = vars.foreach { v => () }
val fails = for (v <- vars) ()
}
// macros.scala
import scala.compiletime._
import scala.deriving._
import scala.quoted._
import scala.annotation.meta.field
object Macros{
private def bindingFunctionBody[A: quoted.Type, B: quoted.Type](f: quoted.Expr[A => B])(using Quotes) =
import quoted.quotes.reflect.*
f.asTerm match
case inlined @ Inlined(
call,
bindings,
block @ Block(
List(
defDef @ DefDef(
name,
paramss @ List(TermParamClause(List(param @ ValDef(paramName, paramTpt, _)))),
tpt,
Some(rhs)
)
),
closureIdent
)
) =>
Inlined
.copy(inlined)(
call,
bindings,
'{ (a: A) =>
${
Block(
List(
ValDef
.copy(param)(paramName, paramTpt, Some('a.asTerm))
.changeOwner(Symbol.spliceOwner)
),
'{
Binding(${ rhs.changeOwner(Symbol.spliceOwner).asExprOf[B] })
}.asTerm.changeOwner(Symbol.spliceOwner)
)
.asExprOf[Binding[B]]
}: Binding[B]
}.asTerm
)
.asExprOf[A => Binding[B]]
case _ =>
'{ (a: A) => Binding.Constant($f(a)): Binding[B] }
end match
end bindingFunctionBody
def foreach[A: quoted.Type, U: quoted.Type](self: quoted.Expr[BindingSeq[A]], f: quoted.Expr[A => U])(using
qctx: Quotes
): quoted.Expr[Unit] = '{ $self.foreachBinding(${ bindingFunctionBody(f) }).bind }
}
Output
-- Error: /Users/wmazur/projects/dotty/bisect/main.scala:21:14 -----------------
21 | val fails = for (v <- vars) ()
| ^^^^^^^^^^^^^^^^^^
|Exception occurred while executing macro expansion.
|java.lang.Exception: Expr cast exception: ((a: scala.Int) => ({
| val v: scala.Int = a
| Binding.apply[scala.Unit](())
|}: Binding[scala.Unit]))
|of type: scala.Function1[scala.Int, scala.Unit]
|did not conform to type: scala.Function1[scala.Int, Binding[scala.Unit]]
|
| at scala.quoted.runtime.impl.QuotesImpl.asExprOf(QuotesImpl.scala:76)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$TreeMethods$.asExprOf(QuotesImpl.scala:119)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$TreeMethods$.asExprOf(QuotesImpl.scala:118)
| at Macros$.bindingFunctionBody(macros.scala:45)
| at Macros$.foreach$$anonfun$1(macros.scala:53)
| at Macros$.foreach$$anonfun$adapted$1(macros.scala:53)
| at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:110)
| at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1563)
| at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:135)
| at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform$$anonfun$1(Trees.scala:1632)
| at scala.collection.immutable.List.mapConserve(List.scala:472)
| at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1632)
| at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1529)
| at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:135)
| at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform$$anonfun$1(Trees.scala:1632)
| at scala.collection.immutable.List.mapConserve(List.scala:472)
| at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1632)
| at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1529)
| at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:135)
| at dotty.tools.dotc.quoted.PickledQuotes$.spliceTerms(PickledQuotes.scala:152)
| at dotty.tools.dotc.quoted.PickledQuotes$.unpickleTerm(PickledQuotes.scala:88)
| at scala.quoted.runtime.impl.QuotesImpl.unpickleExprV2(QuotesImpl.scala:3170)
| at Macros$.foreach(macros.scala:53)
|
|----------------------------------------------------------------------------
|Inline stack trace
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|This location contains code that was inlined from main.scala:15
15 | transparent inline def foreach[U](inline f: A => U): Unit = ${ Macros.foreach('bindingSeq, 'f) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
----------------------------------------------------------------------------
Expectation
Should compile