Skip to content
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

transform.PatternMatcher crash on extracting exported macro-generated unapply #15990

Closed
Adam-Vandervorst opened this issue Sep 7, 2022 · 1 comment

Comments

@Adam-Vandervorst
Copy link

Adam-Vandervorst commented Sep 7, 2022

Compiler version

3.2.1-RC1-bin-20220904-b5fea82-NIGHTLY

Minimized code

I failed to minimize the code and published the code (sbt > test).

Usage site:

println(SizedVector.unapply(v1)) // works fine, prints `(2,3)`
val SizedVector(a, b) = v1 // crashes with the message at the end
println(s"a: $a, b: $b")

Export site:

object SizedVector:
  export be.adamv.macroloop.collection.TupleConstructors.{vectorApply as apply, vectorUnapply as unapply}

Definition site:

object TupleConstructors:
  import be.adamv.macroloop.collection.macros.*
  import compiletime.ops.int.S

  type RepeatN[T, I <: Int] <: Tuple = I match
    case 0 => EmptyTuple
    case S[n] => T *: RepeatN[T, n]

  transparent inline def vectorUnapply[N <: Int, A](inline v: SizedVector[N, A]): RepeatN[A, N] =
    ${ destructVectorImpl[N, A]('v) }

Macro definition site:

def destructVectorImpl[N <: Int : Type, A: Type](elementse: Expr[SizedVector[N, A]])(using Quotes): Expr[RepeatN[A, N]] =
  val size = Type.valueOfConstant[N].get
  val elements = Seq.tabulate(size)(i => '{ $elementse.data(${ Expr(i) }) })

  Expr.ofTupleFromSeq(elements).asInstanceOf[Expr[RepeatN[A, N]]]

Output (click arrow to expand)

[IJ]test
[info] compiling 3 Scala sources to /home/adamv/IdeaProjects/MacroLoop/collection/target/scala-3.2.1-RC1-bin-20220904-b5fea82-NIGHTLY/test-classes ...
[warn] -- Warning: /home/adamv/IdeaProjects/MacroLoop/collection/src/test/scala/VectorBasic.scala:30:19 
[warn] 30 |    val SizedVector(a, b) = v1
[warn]    |        ^^^^^^^^^^^^^^^^^^^^^^
[warn]    |pattern binding uses refutable extractor `{
[warn]    |  final class $anon() extends Object() {
[warn]    |    def unapply(v: be.adamv.macroloop.collection.SizedVector[(2 : Int), Int]): 
[warn]    |      be.adamv.macroloop.collection.TupleConstructors.RepeatN[Int, (2 : Int)]
[warn]    |     = Tuple2.apply[Int, Int](v.data.apply(0), v.data.apply(1))
[warn]    |  }
[warn]    |  new Object {...}()
[warn]    |}`
[warn]    |
[warn]    |If this usage is intentional, this can be communicated by adding `: @unchecked` after the expression,
[warn]    |which may result in a MatchError at runtime.
[warn]    |This patch can be rewritten automatically under -rewrite -source 3.2-migration.
scala.MatchError: List() (of class scala.collection.immutable.Nil$) while running MegaPhase{crossVersionChecks, protectedAccessors, extmethods, uncacheGivenAliases, elimByName, hoistSuperArgs, forwardDepChecks, specializeApplyMethods, tryCatchPatterns, patternMatcher} on /home/adamv/IdeaProjects/MacroLoop/collection/src/test/scala/VectorBasic.scala
[info] exception occurred while compiling /home/adamv/IdeaProjects/MacroLoop/collection/src/test/scala/CrossBasic.scala, /home/adamv/IdeaProjects/MacroLoop/collection/src/test/scala/MatrixBasic.scala, /home/adamv/IdeaProjects/MacroLoop/collection/src/test/scala/VectorBasic.scala
scala.MatchError: List() (of class scala.collection.immutable.Nil$) while compiling /home/adamv/IdeaProjects/MacroLoop/collection/src/test/scala/CrossBasic.scala, /home/adamv/IdeaProjects/MacroLoop/collection/src/test/scala/MatrixBasic.scala, /home/adamv/IdeaProjects/MacroLoop/collection/src/test/scala/VectorBasic.scala
[error] ## Exception when compiling 3 sources to /home/adamv/IdeaProjects/MacroLoop/collection/target/scala-3.2.1-RC1-bin-20220904-b5fea82-NIGHTLY/test-classes
[error] scala.MatchError: List() (of class scala.collection.immutable.Nil$)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.matchArgsPatternPlan$1(PatternMatcher.scala:265)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.matchArgsComponentsPlan$1(PatternMatcher.scala:260)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.matchArgsPlan$1(PatternMatcher.scala:271)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.unapplyPlan$1$$anonfun$1(PatternMatcher.scala:363)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.letAbstract(PatternMatcher.scala:112)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.unapplyPlan$1(PatternMatcher.scala:383)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.patternPlan(PatternMatcher.scala:420)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.caseDefPlan(PatternMatcher.scala:456)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.matchPlan$$anonfun$1$$anonfun$1(PatternMatcher.scala:463)
[error] scala.collection.immutable.List.foldRight(List.scala:352)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.matchPlan$$anonfun$1(PatternMatcher.scala:463)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.letAbstract(PatternMatcher.scala:112)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.matchPlan(PatternMatcher.scala:464)
[error] dotty.tools.dotc.transform.PatternMatcher$Translator.translateMatch(PatternMatcher.scala:1042)
[error] dotty.tools.dotc.transform.PatternMatcher.transformMatch(PatternMatcher.scala:45)
[error] dotty.tools.dotc.transform.MegaPhase.goMatch(MegaPhase.scala:785)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:366)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:427)
[error] dotty.tools.dotc.transform.MegaPhase.mapValDef$1(MegaPhase.scala:234)
[error] dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:239)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:425)
[error] dotty.tools.dotc.transform.MegaPhase.loop$2(MegaPhase.scala:444)
[error] dotty.tools.dotc.transform.MegaPhase.transformBlock(MegaPhase.scala:449)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:298)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:427)
[error] dotty.tools.dotc.transform.MegaPhase.recur$1(MegaPhase.scala:459)
[error] dotty.tools.dotc.transform.MegaPhase.transformTrees(MegaPhase.scala:459)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:279)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:427)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:278)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:427)
[error] dotty.tools.dotc.transform.MegaPhase.loop$1(MegaPhase.scala:438)
[error] dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:438)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:359)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:427)
[error] dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:255)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:425)
[error] dotty.tools.dotc.transform.MegaPhase.loop$1(MegaPhase.scala:438)
[error] dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:438)
[error] dotty.tools.dotc.transform.MegaPhase.mapPackage$1(MegaPhase.scala:379)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:382)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:427)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnit(MegaPhase.scala:454)
[error] dotty.tools.dotc.transform.MegaPhase.run(MegaPhase.scala:466)
[error] dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:316)
[error] scala.collection.immutable.List.map(List.scala:250)
[error] dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:320)
[error] dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:233)
[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:244)
[error] dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:252)
[error] dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:261)
[error] dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:68)
[error] dotty.tools.dotc.Run.compileUnits(Run.scala:261)
[error] dotty.tools.dotc.Run.compileSources(Run.scala:185)
[error] dotty.tools.dotc.Run.compile(Run.scala:169)
[error] dotty.tools.dotc.Driver.doCompile(Driver.scala:35)
[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.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
[error] java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
[error] java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
[error] java.base/java.lang.Thread.run(Thread.java:833)
@Adam-Vandervorst Adam-Vandervorst added itype:bug itype:crash stat:needs triage Every issue needs to have an "area" and "itype" label labels Sep 7, 2022
@Adam-Vandervorst
Copy link
Author

For what it's worth, this does work:

// in main.scala
import compiletime.ops.int.S
type RepeatN[T, I <: Int] <: Tuple = I match
  case 0 => EmptyTuple
  case S[n] => T *: RepeatN[T, n]

abstract class Pair:
  val ar: Array[Int]

object Utils:
  inline def pairUnapply(p: Pair): RepeatN[Int, 2] =
    ${ impl('p) }

object Pair:
  export Utils.pairUnapply as unapply

@main def example =
  val p: Pair = new Pair:
    val ar = Array(1, 2)

  val Pair(x, y) = p
  println(x)
// in macro.scala
import scala.quoted.*

def impl(paire: Expr[Pair])(using Quotes): Expr[RepeatN[Int, 2]] =
  val els = Seq.tabulate(2)(i => '{ $paire.ar(${ Expr(i) }) })
  Expr.ofTupleFromSeq(els).asInstanceOf[Expr[RepeatN[Int, 2]]]

@mbovel mbovel added area:pattern-matching and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Sep 12, 2022
@Kordyjan Kordyjan added this to the Future versions milestone Dec 12, 2022
@dwijnand dwijnand added the stat:needs minimization Needs a self contained minimization label Jan 17, 2023
@dwijnand dwijnand closed this as not planned Won't fix, can't repro, duplicate, stale Jan 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants