Passing opaque type through two wrappers compiled in another module causes the type to lose its identity and opaqueness
Opened this issue · 5 comments
Compiler version
3.3.3
3.4.2
3.5.0-RC1
Minimized code
import scala.quoted.*
class ForeignWrapper1[-A] {
inline def getTypeInfo(inline source: String): Unit =
${ getTypeInfoImpl[A]('source) }
def createWrapper2 = ForeignWrapper2(this)
}
class ForeignWrapper2[-A](val self: ForeignWrapper1[A]) {
inline def getTypeInfo(inline source: String): Unit =
${getTypeInfoImpl[A]('source)}
}
transparent inline def getTypeInfo[T](inline source: String) =
${ getTypeInfoImpl[T]('source) }
def getTypeInfoImpl[T: Type](source: Expr[String])(using ctx: Quotes) : Expr[Unit] = {
import ctx.reflect.*
println("------" + source.valueOrAbort + "---------")
val tpe = TypeRepr.of[T]
println(s"Original: ${tpe.show}")
println(s"Dealias: ${tpe.dealias.show}")
println(s"Dealias dealias: ${tpe.dealias.dealias.show}")
'{ () }
}
object UserName {
opaque type T = String
def apply(s: String): T = s
}
type UserName = UserName.T
class Wrapper1[-A] {
inline def getTypeInfo(inline source: String): Unit =
${ getTypeInfoImpl[A]('source) }
def createWrapper2 = Wrapper2(this)
}
class Wrapper2[-A](val self: Wrapper1[A]) {
inline def getTypeInfo(inline source: String): Unit =
${getTypeInfoImpl[A]('source)}
}
val _ = {
getTypeInfo[UserName.T]("UserName.T - Directly")
getTypeInfo[UserName]("UserName.T - Directly")
val foreignWrapper = ForeignWrapper1[UserName.T]()
foreignWrapper.getTypeInfo("ForeignWrapper1[UserName.T]")
foreignWrapper.createWrapper2.getTypeInfo("ForeignWrapper2[UserName.T]")
val foreignWrapper2 = ForeignWrapper1[UserName]()
foreignWrapper2.getTypeInfo("ForeignWrapper1[UserName]")
foreignWrapper2.createWrapper2.getTypeInfo("ForeignWrapper2[UserName]")
val wrapper = Wrapper1[UserName.T]()
wrapper.getTypeInfo("Wrapper1[UserName.T]")
wrapper.createWrapper2.getTypeInfo("Wrapper2[UserName.T]")
val wrapper2 = Wrapper1[UserName]()
wrapper2.getTypeInfo("Wrapper1[UserName]")
wrapper2.createWrapper2.getTypeInfo("Wrapper2[UserName]")
}
Output
------UserName.T - Directly---------
Original: test$package.UserName.T
Dealias: test$package.UserName.T
Dealias dealias: test$package.UserName.T
------UserName.T - Directly---------
Original: test$package.UserName
Dealias: test$package.UserName.T
Dealias dealias: test$package.UserName.T
------ForeignWrapper1[UserName.T]---------
Original: test$package.UserName.T
Dealias: test$package.UserName.T
Dealias dealias: test$package.UserName.T
------ForeignWrapper2[UserName.T]---------
Original: $proxy1.T
Dealias: java.lang.String
Dealias dealias: java.lang.String
------ForeignWrapper1[UserName]---------
Original: test$package.UserName
Dealias: test$package.UserName.T
Dealias dealias: test$package.UserName.T
------ForeignWrapper2[UserName]---------
Original: test$package.UserName
Dealias: test$package.UserName.T
Dealias dealias: test$package.UserName.T
------Wrapper1[UserName.T]---------
Original: test$package.UserName.T
Dealias: test$package.UserName.T
Dealias dealias: test$package.UserName.T
------Wrapper2[UserName.T]---------
Original: test$package.UserName.T
Dealias: test$package.UserName.T
Dealias dealias: test$package.UserName.T
------Wrapper1[UserName]---------
Original: test$package.UserName
Dealias: test$package.UserName.T
Dealias dealias: test$package.UserName.T
------Wrapper2[UserName]---------
Original: test$package.UserName
Dealias: test$package.UserName.T
Dealias dealias: test$package.UserName.T
Expectation
------ForeignWrapper2[UserName.T]---------
Original: $proxy1.T
Dealias: java.lang.String
Dealias dealias: java.lang.String
Expectation is that opaque type would not become $proxy1.T
that can be dealiased to underlying type.
Not sure if I'm missing something about the reproduction, but trying to compile it with 3.4.2 / 3.5.0-RC1 / nightly gives me the following crash:
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: /Users/pchabelski/IdeaProjects/scala-cli-tests/compiler-repro/repro.scala
during phase: typer
mode: Mode(ImplicitsEnabled)
library version: version 2.13.12
compiler version: version 3.5.1-RC1-bin-20240602-c6fbe6f-NIGHTLY-git-c6fbe6f
settings: -classpath /Users/pchabelski/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.5.1-RC1-bin-20240602-c6fbe6f-NIGHTLY/scala3-library_3-3.5.1-RC1-bin-20240602-c6fbe6f-NIGHTLY.jar:/Users/pchabelski/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.12/scala-library-2.13.12.jar -d /Users/pchabelski/IdeaProjects/scala-cli-tests/compiler-repro/.scala-build/compiler-repro_4d37e6c5c0-fb1e690db3/classes/main -java-output-version 17 -sourceroot /Users/pchabelski/IdeaProjects/scala-cli-tests/compiler-repro
Exception while compiling /Users/pchabelski/IdeaProjects/scala-cli-tests/compiler-repro/repro.scala, /Users/pchabelski/IdeaProjects/scala-cli-tests/compiler-repro/Macro.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: <no file>
during phase: parser
mode: Mode()
library version: version 2.13.12
compiler version: version 3.5.1-RC1-bin-20240602-c6fbe6f-NIGHTLY-git-c6fbe6f
settings: -classpath /Users/pchabelski/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.5.1-RC1-bin-20240602-c6fbe6f-NIGHTLY/scala3-library_3-3.5.1-RC1-bin-20240602-c6fbe6f-NIGHTLY.jar:/Users/pchabelski/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.12/scala-library-2.13.12.jar -d /Users/pchabelski/IdeaProjects/scala-cli-tests/compiler-repro/.scala-build/compiler-repro_4d37e6c5c0-fb1e690db3/classes/main -java-output-version 17 -sourceroot /Users/pchabelski/IdeaProjects/scala-cli-tests/compiler-repro
Exception in thread "main" dotty.tools.dotc.core.Denotations$StaleSymbolException: stale symbol; module class Wrapper1$#4131 in module class <empty>, defined in Period(2.1-8), is referred to in run Period(3.1)
at dotty.tools.dotc.core.Denotations$SingleDenotation.staleSymbolError(Denotations.scala:961)
at dotty.tools.dotc.core.Denotations$SingleDenotation.bringForward(Denotations.scala:759)
at dotty.tools.dotc.core.Denotations$SingleDenotation.toNewRun$1(Denotations.scala:806)
at dotty.tools.dotc.core.Denotations$SingleDenotation.current(Denotations.scala:877)
at dotty.tools.dotc.core.Symbols$Symbol.recomputeDenot(Symbols.scala:124)
at dotty.tools.dotc.core.Symbols$Symbol.computeDenot(Symbols.scala:118)
at dotty.tools.dotc.core.Symbols$Symbol.denot(Symbols.scala:109)
at dotty.tools.dotc.core.SymDenotations$ModuleCompleter.complete(SymDenotations.scala:2817)
at dotty.tools.dotc.core.SymDenotations$SymDenotation.completeFrom(SymDenotations.scala:175)
at dotty.tools.dotc.core.Denotations$Denotation.completeInfo$1(Denotations.scala:190)
at dotty.tools.dotc.core.Denotations$Denotation.info(Denotations.scala:192)
at dotty.tools.dotc.core.SymDenotations$SymDenotation.ensureCompleted(SymDenotations.scala:393)
at dotty.tools.dotc.core.SymDenotations$SymDenotation.flags(SymDenotations.scala:66)
at dotty.tools.dotc.core.SymDenotations$SymDenotation.is(SymDenotations.scala:112)
at dotty.tools.dotc.typer.Typer.isSelfDenot$1(Typer.scala:396)
at dotty.tools.dotc.typer.Typer.loop$1(Typer.scala:489)
at dotty.tools.dotc.typer.Typer.findRefRecur$1(Typer.scala:553)
at dotty.tools.dotc.typer.Typer.findRef(Typer.scala:556)
at dotty.tools.dotc.typer.Typer.typedIdent(Typer.scala:617)
at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3371)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3481)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3559)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3563)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3674)
at dotty.tools.dotc.typer.Applications.typedTypeApply(Applications.scala:1284)
at dotty.tools.dotc.typer.Applications.typedTypeApply$(Applications.scala:434)
at dotty.tools.dotc.typer.Typer.typedTypeApply(Typer.scala:145)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3417)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3482)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3559)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3563)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3674)
at dotty.tools.dotc.typer.Applications.realApply$1(Applications.scala:1040)
at dotty.tools.dotc.typer.Applications.typedApply(Applications.scala:1231)
at dotty.tools.dotc.typer.Applications.typedApply$(Applications.scala:434)
at dotty.tools.dotc.typer.Typer.typedApply(Typer.scala:145)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3397)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3482)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3559)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3563)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3674)
at dotty.tools.dotc.typer.Namer.typedAheadExpr$$anonfun$1(Namer.scala:1747)
at dotty.tools.dotc.typer.Namer.typedAhead(Namer.scala:1737)
at dotty.tools.dotc.typer.Namer.typedAheadExpr(Namer.scala:1747)
at dotty.tools.dotc.typer.Namer.typedAheadRhs$1$$anonfun$1(Namer.scala:2073)
at dotty.tools.dotc.inlines.PrepareInlineable$.dropInlineIfError(PrepareInlineable.scala:256)
at dotty.tools.dotc.typer.Namer.typedAheadRhs$1(Namer.scala:2073)
at dotty.tools.dotc.typer.Namer.rhsType$1(Namer.scala:2081)
at dotty.tools.dotc.typer.Namer.cookedRhsType$1(Namer.scala:2100)
at dotty.tools.dotc.typer.Namer.lhsType$1(Namer.scala:2101)
at dotty.tools.dotc.typer.Namer.inferredResultType(Namer.scala:2112)
at dotty.tools.dotc.typer.Namer.inferredType$1(Namer.scala:1779)
at dotty.tools.dotc.typer.Namer.valOrDefDefSig(Namer.scala:1785)
at dotty.tools.dotc.typer.Namer$Completer.typeSig(Namer.scala:823)
at dotty.tools.dotc.typer.Namer$Completer.completeInCreationContext(Namer.scala:974)
at dotty.tools.dotc.typer.Namer$Completer.complete(Namer.scala:850)
at dotty.tools.dotc.core.SymDenotations$SymDenotation.completeFrom(SymDenotations.scala:175)
at dotty.tools.dotc.core.Denotations$Denotation.completeInfo$1(Denotations.scala:190)
at dotty.tools.dotc.core.Denotations$Denotation.info(Denotations.scala:192)
at dotty.tools.dotc.core.SymDenotations$SymDenotation.ensureCompleted(SymDenotations.scala:393)
at dotty.tools.dotc.typer.Typer.retrieveSym(Typer.scala:3344)
at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3369)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3481)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3559)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3563)
at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3585)
at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3631)
at dotty.tools.dotc.typer.Typer.typedBlockStats(Typer.scala:1375)
at dotty.tools.dotc.typer.Typer.typedBlock(Typer.scala:1379)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3405)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3482)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3559)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3563)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3674)
at dotty.tools.dotc.typer.Typer.typedMatch(Typer.scala:1972)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3412)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3482)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3559)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3563)
at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3612)
at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3631)
at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:3079)
at dotty.tools.dotc.typer.Typer.typedTypeOrClassDef$1(Typer.scala:3385)
at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3389)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3481)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3559)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3563)
at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3585)
at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3631)
at dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:3212)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3431)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3482)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3559)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3563)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3674)
at dotty.tools.dotc.typer.TyperPhase.typeCheck$$anonfun$1(TyperPhase.scala:47)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
at dotty.tools.dotc.core.Phases$Phase.monitor(Phases.scala:503)
at dotty.tools.dotc.typer.TyperPhase.typeCheck(TyperPhase.scala:53)
at dotty.tools.dotc.typer.TyperPhase.$anonfun$4(TyperPhase.scala:99)
at scala.collection.Iterator$$anon$6.hasNext(Iterator.scala:479)
at scala.collection.Iterator$$anon$9.hasNext(Iterator.scala:583)
at scala.collection.immutable.List.prependedAll(List.scala:152)
at scala.collection.immutable.List$.from(List.scala:684)
at scala.collection.immutable.List$.from(List.scala:681)
at scala.collection.IterableOps$WithFilter.map(Iterable.scala:898)
at dotty.tools.dotc.typer.TyperPhase.runOn(TyperPhase.scala:98)
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.compileUnits(Run.scala:288)
at dotty.tools.dotc.Run.compileSuspendedUnits(Run.scala:410)
at dotty.tools.dotc.Driver.finish(Driver.scala:63)
at dotty.tools.dotc.Driver.doCompile(Driver.scala:38)
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.dotc.Main.main(Main.scala)
@andrzejressel did you pass any compiler options when reproducing this?
Either way, tagging this as a crash issue for now.
@Gedochao No, everything is default: https://github.com/andrzejressel/scala3-20449/actions/runs/9397702223/job/25881452117
Looks like the crash happens only if both files are compiled in the same compilation run
Also it seems that the overzealous dealiasing issue happens only when compiling in two compilation runs. Interesting...
Also found this:
import scala.quoted.*
transparent inline def getTypeInfo[T]() = ${ getTypeInfoImpl[T] }
def getTypeInfoImpl[T: Type](using ctx: Quotes): Expr[Unit] = '{ () }
class Wrapper1[A]
val _ = {
getTypeInfo[Any]()
val wrapper2 = Wrapper1[Any]()
}
producing:
-- [E006] Not Found Error: M2.scala:5:17 ---------------------------------------
5 | val wrapper2 = Wrapper1[Any]()
| ^^^^^^^^
| Not found: Wrapper1 - did you mean wrapper2?
|
| longer explanation available when compiling with `-explain`
It seems we lose some part of context when suspending to expand a macro