Skip to content

Extracting contravariant type parameter in match breaks a quote #15779

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
prolativ opened this issue Jul 28, 2022 · 0 comments · Fixed by #16570
Closed

Extracting contravariant type parameter in match breaks a quote #15779

prolativ opened this issue Jul 28, 2022 · 0 comments · Fixed by #16570
Milestone

Comments

@prolativ
Copy link
Contributor

Compiler version

3.2.0-RC3 and earlier

Minimized code

Encoder.scala

import scala.quoted._
import scala.deriving.Mirror

trait Encoder[-A]

trait PrimitiveEncoder[A] extends Encoder[A]

given intOpt: PrimitiveEncoder[Option[Int]] with {}
  
given primitiveNotNull[T](using e: Encoder[Option[T]]): PrimitiveEncoder[T] =
  new PrimitiveEncoder[T] {}

transparent inline given fromMirror[A]: Any = ${ fromMirrorImpl[A] }

def fromMirrorImpl[A : Type](using q: Quotes): Expr[Any] =
  Expr.summon[Mirror.Of[A]].get match
    case '{ ${mirror}: Mirror.ProductOf[A] { type MirroredElemTypes = elementTypes } } =>
      val encoder = Type.of[elementTypes] match
        case '[tpe *: EmptyTuple] =>
          Expr.summon[Encoder[tpe]].get

      encoder match
        case '{ ${encoder}: Encoder[tpe] } => println("AAA")
        case _ => println("BBB")

      encoder match
        case '{ ${encoder}: Encoder[tpe] } => println("AAA")
        case _ => println("BBB")

      encoder

Main.scala

case class JustInt(i: Int)

val x = fromMirror[JustInt]

Output

AAA
BBB
java.lang.AssertionError: assertion failed: unresolved symbols: type tpe (line 22) #29193 when pickling Main.scala while compiling Encoder.scala, Main.scala
[error] ## Exception when compiling 2 sources to dotty-test/tmp3/target/scala-3.2.0-RC3/classes
[error] java.lang.AssertionError: assertion failed: unresolved symbols: type tpe (line 22) #29193 when pickling Main.scala
[error] scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
[error] dotty.tools.dotc.core.tasty.TreePickler.pickle(TreePickler.scala:783)
[error] dotty.tools.dotc.transform.Pickler.run$$anonfun$1$$anonfun$1(Pickler.scala:72)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
[error] scala.collection.immutable.List.foreach(List.scala:333)
[error] dotty.tools.dotc.transform.Pickler.run$$anonfun$1(Pickler.scala:110)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
[error] scala.collection.immutable.List.foreach(List.scala:333)
[error] dotty.tools.dotc.transform.Pickler.run(Pickler.scala:110)
[error] dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:311)
[error] scala.collection.immutable.List.map(List.scala:246)
[error] dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:312)
[error] dotty.tools.dotc.transform.Pickler.runOn(Pickler.scala:115)
[error] dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:234)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
[error] scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1328)
[error] dotty.tools.dotc.Run.runPhases$1(Run.scala:245)
[error] dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:253)
[error] dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:262)
[error] dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:68)
[error] dotty.tools.dotc.Run.compileUnits(Run.scala:262)
[error] dotty.tools.dotc.Run.compileUnits(Run.scala:192)
[error] dotty.tools.dotc.Driver.finish(Driver.scala:56)
[error] dotty.tools.dotc.Driver.doCompile(Driver.scala:36)
[error] dotty.tools.xsbt.CompilerBridgeDriver.run(CompilerBridgeDriver.java:88)
[error] dotty.tools.xsbt.CompilerBridge.run(CompilerBridge.java:22)
[error] sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:91)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$7(MixedAnalyzingCompiler.scala:192)
[error] scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
[error] sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:247)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4(MixedAnalyzingCompiler.scala:182)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4$adapted(MixedAnalyzingCompiler.scala:163)
[error] sbt.internal.inc.JarUtils$.withPreviousJar(JarUtils.scala:239)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compileScala$1(MixedAnalyzingCompiler.scala:163)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:210)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:528)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:528)
[error] sbt.internal.inc.Incremental$.$anonfun$apply$5(Incremental.scala:177)
[error] sbt.internal.inc.Incremental$.$anonfun$apply$5$adapted(Incremental.scala:175)
[error] sbt.internal.inc.Incremental$$anon$2.run(Incremental.scala:461)
[error] sbt.internal.inc.IncrementalCommon$CycleState.next(IncrementalCommon.scala:116)
[error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:56)
[error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:52)
[error] sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:263)
[error] sbt.internal.inc.Incremental$.$anonfun$incrementalCompile$8(Incremental.scala:416)
[error] sbt.internal.inc.Incremental$.withClassfileManager(Incremental.scala:503)
[error] sbt.internal.inc.Incremental$.incrementalCompile(Incremental.scala:403)
[error] sbt.internal.inc.Incremental$.apply(Incremental.scala:169)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:528)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:482)
[error] sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:332)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:420)
[error] sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:137)
[error] sbt.Defaults$.compileIncrementalTaskImpl(Defaults.scala:2366)
[error] sbt.Defaults$.$anonfun$compileIncrementalTask$2(Defaults.scala:2316)
[error] sbt.internal.server.BspCompileTask$.$anonfun$compute$1(BspCompileTask.scala:30)
[error] sbt.internal.io.Retry$.apply(Retry.scala:46)
[error] sbt.internal.io.Retry$.apply(Retry.scala:28)
[error] sbt.internal.io.Retry$.apply(Retry.scala:23)
[error] sbt.internal.server.BspCompileTask$.compute(BspCompileTask.scala:30)
[error] sbt.Defaults$.$anonfun$compileIncrementalTask$1(Defaults.scala:2314)
[error] scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error] sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
[error] sbt.std.Transform$$anon$4.work(Transform.scala:68)
[error] sbt.Execute.$anonfun$submit$2(Execute.scala:282)
[error] sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
[error] sbt.Execute.work(Execute.scala:291)
[error] sbt.Execute.$anonfun$submit$1(Execute.scala:282)
[error] sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error] sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
[error] java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error] java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error] java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error] java.lang.Thread.run(Thread.java:748)
[error]            
[error] stack trace is suppressed; run last tmp3 / Compile / compileIncremental for the full output
[error] (tmp3 / Compile / compileIncremental) java.lang.AssertionError: assertion failed: unresolved symbols: type tpe (line 22) #29193 when pickling Main.scala

Expectation

This should compile successfully, without breaking the pickler.

It looks like an attempt to extract a type parameter from the type of a quoted expression in a match somehow mutates the quote: The first occurrence of

      encoder match
        case '{ ${encoder}: Encoder[tpe] } => println("AAA")
        case _ => println("BBB")

prints AAA, the second one prints BBB.

On the other hand nothing breaks if at least one of the modifications below is performed:

  • Encoder is declared as invariant
  • PrimitiveEncoder is declared as contravariant
  • the definition of JustInt gets moved to Encoder.scala
  • case '{ ${encoder}: Encoder[tpe] } => println("AAA") branch gets removed from both matches
  • the return value of fromMirrorImpl is something else than encoder
@Kordyjan Kordyjan added this to the Future versions milestone Dec 12, 2022
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 9, 2023
The issue was that an uninstantiated type variable escaped the implicit
search and was then affected by the quote pattern match.

Fixes scala#15779
Fixes scala#16636
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 16, 2023
The issue was that an uninstantiated type variable escaped the implicit
search and was then affected by the quote pattern match.

Fixes scala#15779
Fixes scala#16636
smarter added a commit that referenced this issue Jan 16, 2023
Trees are only checked if `-Xcheck-macros` is enabled.

Fixes:
 - Add missing positions to `{ValDef,Bind}.apply`
 - Inline by-name ascribed param
 - Unbound type variables after implicit search
 - Fixes #15779
 - Fixes #16636
little-inferno pushed a commit to little-inferno/dotty that referenced this issue Jan 25, 2023
The issue was that an uninstantiated type variable escaped the implicit
search and was then affected by the quote pattern match.

Fixes scala#15779
Fixes scala#16636
@Kordyjan Kordyjan modified the milestones: Future versions, 3.3.0 Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants