- Notifications
You must be signed in to change notification settings - Fork 1.1k
Open
Labels
area:compiler-pluginsIssues tied with handling of compiler plugins.Issues tied with handling of compiler plugins.area:inlineitype:bugitype:crash
Description
Compiler version
3.3.5, 3.7.2
Explanation
Encountered while migrating the Chisel language to Scala 3. In Chisel, we use plugins to insert typed ASTs to certain user-facing types like Bundles.
In the minimized plugin code below, a plugin is adding a method called _doNothing
to all subtypes of Okable
. In the test code, we're passing an anonymous Okable
subtype by-name to the inline method foo
. This construction causes a compiler crash during erasure when the compiler attempts to create a path to _doNothing
.
Minimized code
Plugin with Scala-CLI header
plugin.scala
//> using scala "3.7.2" //> using dep "org.scala-lang::scala3-compiler:3.7.2" //> using resourceDir "resources" import dotty.tools.dotc.report import dotty.tools.dotc.plugins.{PluginPhase, StandardPlugin} import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.ast.tpd.Tree import dotty.tools.dotc.ast.tpd.TreeOps import dotty.tools.dotc.CompilationUnit import dotty.tools.dotc.core.Phases.Phase import dotty.tools.dotc.typer.TyperPhase import dotty.tools.dotc.parsing._ import dotty.tools.dotc.core.Names import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Constants.* import dotty.tools.dotc.core.Contexts.* import dotty.tools.dotc.core.Symbols.* import dotty.tools.dotc.core.Types.* class MyPluginPhase extends PluginPhase { val phaseName: String = "MyPluginPhase" override val runsAfter = Set(TyperPhase.name) def isOkable(t: Type)(using Context): Boolean = { val okableTpe = requiredClass("bug.Okable") t.baseClasses.contains(okableTpe) } def genOkable(outer: tpd.TypeDef)(using ctx: Context): tpd.DefDef = { val newExpr = tpd.New(outer.symbol.typeRef, Nil) val okableTpe = requiredClassRef("bug.Okable") val okableSym = newSymbol( outer.symbol, Names.termName("_makeOkable"), Flags.Method | Flags.Override, MethodType(Nil, Nil, okableTpe) ) tpd.DefDef(okableSym.asTerm, _ => newExpr) } override def transformTypeDef(okable: tpd.TypeDef)(using Context): tpd.Tree = { if (isOkable(okable.tpe) && okable.isClassDef && !okable.symbol.flags.is(Flags.Abstract)) { val thiz: tpd.This = tpd.This(okable.symbol.asClass) val printsOkDef = genOkable(okable) okable match { case td @ tpd.TypeDef(name, tmpl: tpd.Template) => { val newDefs = printsOkDef.toList val newTemplate = if (tmpl.body.size >= 1) cpy.Template(tmpl)(body = newDefs ++: tmpl.body) else cpy.Template(tmpl)(body = newDefs) tpd.cpy.TypeDef(td)(name, newTemplate) } case _ => super.transformTypeDef(okable) } } else { super.transformTypeDef(okable) } } } class MyPlugin extends StandardPlugin { val name: String = "MyPlugin" override val description: String = "MyPlugin" override def init(options: List[String]): List[PluginPhase] = { (new MyPluginPhase) :: Nil } }
Create a resource file with:
mkdir -p resources echo "pluginClass=MyPlugin" > resources/plugin.properties
Package with Scala-CLI:
scala-cli --power package plugin.scala -o plugin.jar --assembly --preamble=false
Test code:
test.scala
package bug abstract class Okable { def _makeOkable: Okable = ??? } // Plugin adds a _makeOkable override for all Okable abstract class SomeClass extends Okable class SomeChildClass extends SomeClass class Test { inline def foo[A](a: => A): A = a foo { val sc = new SomeClass { val scc = new SomeChildClass } } }
Compile with (crashes)
scalac -Xplugin:plugin.jar test.scala
Output (click arrow to expand)
unhandled exception while running erasure on test.scala An unhandled exception was thrown in the compiler. Please file a crash report here: https://github.com/scala/scala3/issues/new/choose For non-enriched exceptions, compile with -Xno-enrich-error-messages. while compiling: test.scala during phase: erasure mode: Mode(ImplicitsEnabled) library version: version 2.13.15 compiler version: version 3.6.2 settings: -Vprint List(MyPlugin) -Xplugin List(plugin.jar) Exception in thread "main" java.lang.AssertionError: assertion failed: missing outer accessor in class Okable at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8) at dotty.tools.dotc.transform.ExplicitOuter$.dotty$tools$dotc$transform$ExplicitOuter$$$outerParamAccessor(ExplicitOuter.scala:236) at dotty.tools.dotc.transform.ExplicitOuter$OuterOps$.loop$1(ExplicitOuter.scala:460) at dotty.tools.dotc.transform.ExplicitOuter$OuterOps$.path$extension(ExplicitOuter.scala:469) at dotty.tools.dotc.transform.Erasure$Typer.typedThis(Erasure.scala:814) at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3497) at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3581) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3658) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662) at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3773) at dotty.tools.dotc.transform.Erasure$Typer.$anonfun$7(Erasure.scala:866) at dotty.tools.dotc.core.Decorators$.zipWithConserve(Decorators.scala:160) at dotty.tools.dotc.transform.Erasure$Typer.typedApply(Erasure.scala:866) at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3496) at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3581) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3658) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662) at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3773) at dotty.tools.dotc.typer.Typer.$anonfun$66(Typer.scala:2897) at dotty.tools.dotc.inlines.PrepareInlineable$.dropInlineIfError(PrepareInlineable.scala:256) at dotty.tools.dotc.typer.Typer.typedDefDef(Typer.scala:2897) at dotty.tools.dotc.transform.Erasure$Typer.typedDefDef(Erasure.scala:972) at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3478) at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3580) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3658) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662) at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3684) at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3730) at dotty.tools.dotc.transform.Erasure$Typer.typedStats(Erasure.scala:1085) at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:3160) at dotty.tools.dotc.transform.Erasure$Typer.typedClassDef(Erasure.scala:1061) at dotty.tools.dotc.typer.Typer.typedTypeOrClassDef$1(Typer.scala:3484) at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3488) at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3580) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3658) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662) at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3684) at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3730) at dotty.tools.dotc.transform.Erasure$Typer.typedStats(Erasure.scala:1085) at dotty.tools.dotc.typer.Typer.typedBlockStats(Typer.scala:1427) at dotty.tools.dotc.typer.Typer.typedBlock(Typer.scala:1431) at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3504) at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3581) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3658) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662) at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3773) at dotty.tools.dotc.typer.Typer.typedValDef(Typer.scala:2834) at dotty.tools.dotc.transform.Erasure$Typer.typedValDef(Erasure.scala:923) at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3475) at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3580) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3658) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662) at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3684) at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3730) at dotty.tools.dotc.transform.Erasure$Typer.typedStats(Erasure.scala:1085) at dotty.tools.dotc.typer.Typer.typedBlockStats(Typer.scala:1427) at dotty.tools.dotc.typer.Typer.typedBlock(Typer.scala:1431) at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3504) at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3581) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3658) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662) at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3773) at dotty.tools.dotc.typer.Typer.$anonfun$66(Typer.scala:2897) at dotty.tools.dotc.inlines.PrepareInlineable$.dropInlineIfError(PrepareInlineable.scala:256) at dotty.tools.dotc.typer.Typer.typedDefDef(Typer.scala:2897) at dotty.tools.dotc.transform.Erasure$Typer.typedDefDef(Erasure.scala:972) at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3478) at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3580) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3658) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662) at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3684) at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3730) at dotty.tools.dotc.transform.Erasure$Typer.typedStats(Erasure.scala:1085) at dotty.tools.dotc.typer.Typer.typedBlockStats(Typer.scala:1427) at dotty.tools.dotc.typer.ReTyper.typedInlined(ReTyper.scala:99) at dotty.tools.dotc.transform.Erasure$Typer.typedInlined(Erasure.scala:914) at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3519) at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3581) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3658) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662) at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3711) at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3730) at dotty.tools.dotc.transform.Erasure$Typer.typedStats(Erasure.scala:1085) at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:3160) at dotty.tools.dotc.transform.Erasure$Typer.typedClassDef(Erasure.scala:1061) at dotty.tools.dotc.typer.Typer.typedTypeOrClassDef$1(Typer.scala:3484) at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3488) at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3580) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3658) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662) at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3684) at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3730) at dotty.tools.dotc.transform.Erasure$Typer.typedStats(Erasure.scala:1085) at dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:3293) at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3530) at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3581) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3658) at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3662) at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3773) at dotty.tools.dotc.transform.Erasure.run(Erasure.scala:146) at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:380) at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15) at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10) at scala.collection.immutable.List.foreach(List.scala:334) at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:373) at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:343) at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15) at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10) at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323) at dotty.tools.dotc.Run.runPhases$1(Run.scala:336) at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:384) at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:396) at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:69) at dotty.tools.dotc.Run.compileUnits(Run.scala:396) at dotty.tools.dotc.Run.compileSources(Run.scala:282) at dotty.tools.dotc.Run.compile(Run.scala:267) at dotty.tools.dotc.Driver.doCompile(Driver.scala:37) at dotty.tools.dotc.Driver.process(Driver.scala:201) at dotty.tools.dotc.Driver.process(Driver.scala:169) at dotty.tools.dotc.Driver.process(Driver.scala:181) at dotty.tools.dotc.Driver.main(Driver.scala:211) at dotty.tools.MainGenericCompiler$.run$1(MainGenericCompiler.scala:162) at dotty.tools.MainGenericCompiler$.main(MainGenericCompiler.scala:186) at dotty.tools.MainGenericCompiler.main(MainGenericCompiler.scala) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at coursier.bootstrap.launcher.a.a(Unknown Source) at coursier.bootstrap.launcher.Launcher.main(Unknown Source)
Metadata
Metadata
Assignees
Labels
area:compiler-pluginsIssues tied with handling of compiler plugins.Issues tied with handling of compiler plugins.area:inlineitype:bugitype:crash