To reproduce execute:
git clone https://github.com/zio/izumi-reflect.git
cd izumi-reflect
git checkout feature/dotty-macro-expansion-fails-when-not-inside-type-ascripted-method
sbt '++0.24.0-bin-20200420-c560211-NIGHTLY test:compile'
scala[error] -- Error: /private/tmp/izumi-reflect/izumi-reflect/izumi-reflect/src/test/scala/izumi/reflect/test/CurrentDottySupportExtentTest.scala:26:22
[error] 26 | val bazTag = LTT[Baz]
[error] | ^^^^^^^^
[error] |Exception occurred while executing macro expansion.
[error] |scala.NotImplementedError: an implementation is missing
[error] | at scala.Predef$.$qmark$qmark$qmark(Predef.scala:347)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspector.scala:120)
[error] | at izumi.reflect.dottyreflection.Inspector.prefixOf(Inspector.scala:132)
[error] | at izumi.reflect.dottyreflection.Inspector.asNameRefSym(Inspector.scala:219)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspector.scala:113)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectTree(Inspector.scala:107)
[error] | at izumi.reflect.dottyreflection.Inspector.buildTypeRef(Inspector.scala:33)
[error] | at izumi.reflect.dottyreflection.TypeInspections$.apply(TypeInspections.scala:10)
[error] | at izumi.reflect.dottyreflection.Inspect$.inspectAny(Inspect.scala:21)
[error] |
[error] | This location contains code that was inlined from CurrentDottySupportExtentTest.scala:26
[error] | This location contains code that was inlined from package.scala:73
[error] -- Error: /private/tmp/izumi-reflect/izumi-reflect/izumi-reflect/src/test/scala/izumi/reflect/test/CurrentDottySupportExtentTest.scala:27:23
[error] 27 | val bazTag2 = LTT[Baz]
[error] | ^^^^^^^^
[error] |Exception occurred while executing macro expansion.
[error] |scala.NotImplementedError: an implementation is missing
[error] | at scala.Predef$.$qmark$qmark$qmark(Predef.scala:347)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspector.scala:120)
[error] | at izumi.reflect.dottyreflection.Inspector.prefixOf(Inspector.scala:132)
[error] | at izumi.reflect.dottyreflection.Inspector.asNameRefSym(Inspector.scala:219)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspector.scala:113)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectTree(Inspector.scala:107)
[error] | at izumi.reflect.dottyreflection.Inspector.buildTypeRef(Inspector.scala:33)
[error] | at izumi.reflect.dottyreflection.TypeInspections$.apply(TypeInspections.scala:10)
[error] | at izumi.reflect.dottyreflection.Inspect$.inspectAny(Inspect.scala:21)
[error] |
[error] | This location contains code that was inlined from CurrentDottySupportExtentTest.scala:27
[error] | This location contains code that was inlined from package.scala:73
[error] -- Error: /private/tmp/izumi-reflect/izumi-reflect/izumi-reflect/src/test/scala/izumi/reflect/test/CurrentDottySupportExtentTest.scala:29:23
[error] 29 | val barXTag = LTT[Bar[X]]
[error] | ^^^^^^^^^^^
[error] |Exception occurred while executing macro expansion.
[error] |scala.NotImplementedError: an implementation is missing
[error] | at scala.Predef$.$qmark$qmark$qmark(Predef.scala:347)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspector.scala:120)
[error] | at izumi.reflect.dottyreflection.Inspector.prefixOf(Inspector.scala:132)
[error] | at izumi.reflect.dottyreflection.Inspector.asNameRefSym(Inspector.scala:219)
[error] | at izumi.reflect.dottyreflection.Inspector.asNameRef(Inspector.scala:212)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectTType(Inspector.scala:66)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectTree(Inspector.scala:105)
[error] | at izumi.reflect.dottyreflection.Inspector.buildTypeRef(Inspector.scala:33)
[error] | at izumi.reflect.dottyreflection.TypeInspections$.apply(TypeInspections.scala:10)
[error] | at izumi.reflect.dottyreflection.Inspect$.inspectAny(Inspect.scala:21)
[error] |
[error] | This location contains code that was inlined from CurrentDottySupportExtentTest.scala:29
[error] | This location contains code that was inlined from package.scala:73
Compilation succeeds if the commented out wrappng method def test(): Unit = { ... } is uncommented.
That is, the content of the quoted.Type[_] value depends directly on whether or not the LTT inline method is called inside a def test or inside the class body, even though the types referred to are defined inside the current block in both situations. Moreover if the inline calls are placed inside a method, but without a type ascription, def test() = { ... }, the result is the same error.
/cc @nicolasstucki
Can you try to minimize this into a self contained example? We will treat these with priority.
@odersky I'll try, but I probably wouldn't have enough time until next week. As it is, the macro codebase of that project is fairly small, but yes, it's not an isolated snippet and may be not ideal for debugging.
@neko-kai what tree do you get in Inspector.scala#L118? I notice that you don't match ValDef.
@nicolasstucki
I've pushed a commit adding debug messages to exceptions in that branch. The tree is a ValDef - but that's not supposed to be there, we're recursing over symbol.tree to collect information about the inheritance hierarchy, so we need the tree to always be the definition tree, unless there's some other way to traverse the type hierarchy.
Error:(26, 23) Exception occurred while executing macro expansion.
java.lang.RuntimeException: SYMBOL TREE, UNSUPPORTED: class dotty.tools.dotc.ast.Trees$ValDef - ValDef(<local CurrentDottySupportExtentTest>,TypeTree[NoType],EmptyTree)
at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspector.scala:120)
at izumi.reflect.dottyreflection.Inspector.prefixOf(Inspector.scala:132)
at izumi.reflect.dottyreflection.Inspector.asNameRefSym(Inspector.scala:217)
at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspector.scala:113)
at izumi.reflect.dottyreflection.Inspector.inspectTree(Inspector.scala:107)
at izumi.reflect.dottyreflection.Inspector.buildTypeRef(Inspector.scala:33)
at izumi.reflect.dottyreflection.TypeInspections$.apply(TypeInspections.scala:10)
at izumi.reflect.dottyreflection.Inspect$.inspectAny(Inspect.scala:21)
val bazTag = LTT[Baz]
Note, if I add code to recurse on the ValDef#tpt it arrives nowhere anyway:
Error:(26, 23) Exception occurred while executing macro expansion.
java.lang.RuntimeException: TTYPE, UNSUPPORTED: class dotty.tools.dotc.core.Types$NoType$ - NoType
at izumi.reflect.dottyreflection.Inspector.inspectTType(Inspector.scala:94)
at izumi.reflect.dottyreflection.Inspector.inspectTree(Inspector.scala:105)
at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspector.scala:119)
at izumi.reflect.dottyreflection.Inspector.prefixOf(Inspector.scala:134)
at izumi.reflect.dottyreflection.Inspector.asNameRefSym(Inspector.scala:219)
at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspector.scala:113)
at izumi.reflect.dottyreflection.Inspector.inspectTree(Inspector.scala:107)
at izumi.reflect.dottyreflection.Inspector.buildTypeRef(Inspector.scala:33)
at izumi.reflect.dottyreflection.TypeInspections$.apply(TypeInspections.scala:10)
at izumi.reflect.dottyreflection.Inspect$.inspectAny(Inspect.scala:21)
val bazTag = LTT[Baz]
Also, in the macro expansion for LTT[List[Int]], below LTT[Baz] aboe, a Types.LazyRef occurs, which seems like is a very low-level type that doesn't have any methods in tasty-reflect, specifically there's no way to call .underlying and dereference it:
[error] 52 | val listIntTag0 = LTT[List[Int]]
[error] | ^^^^^^^^^^^^^^
[error] |Exception occurred while executing macro expansion.
[error] |java.lang.RuntimeException: TTYPE, UNSUPPORTED: class dotty.tools.dotc.core.Types$LazyRef - LazyRef(...)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectTType(Inspector.scala:94)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectToB(Inspector.scala:154)
[error] | at izumi.reflect.dottyreflection.Inspector.$anonfun$3(Inspector.scala:64)
[error] | at scala.collection.immutable.List.map(List.scala:223)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectTType(Inspector.scala:64)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectTType(Inspector.scala:71)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectTType(Inspector.scala:90)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectTree(Inspector.scala:105)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspector.scala:115)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectTType(Inspector.scala:87)
[error] | at izumi.reflect.dottyreflection.Inspector.inspectToB(Inspector.scala:154)
[error] | at izumi.reflect.dottyreflection.Inspector.$anonfun$3(Inspector.scala:64)
[error] | at scala.collection.immutable.List.map(List.scala:223)
Still need a self contained minimized example
@nicolasstucki
I've made a minimized example here:
https://github.com/7mind/dottyreflection-repro
You can test using that repo, It consists of just one file with minimized code and two files with test cases:
CyclicReferenceException depending on the point in code at which the inline was called:package test
import izumi.reflect.dottyreflection.Inspect.inspect
object Test1 extends App {
// ok in class body
class Foo
println(inspect[Foo])
// not ok in expression
def test() = {
locally {
inspect[Foo]
}
}
}
Error:(14, 14) Exception occurred while executing macro expansion.
dotty.tools.dotc.core.CyclicReference:
at dotty.tools.dotc.core.CyclicReference$.apply(TypeErrors.scala:156)
at dotty.tools.dotc.core.SymDenotations$SymDenotation.completeFrom(SymDenotations.scala:257)
at dotty.tools.dotc.core.Denotations$Denotation.completeInfo$1(Denotations.scala:186)
at dotty.tools.dotc.core.Denotations$Denotation.info(Denotations.scala:188)
at dotty.tools.dotc.ast.tpd$.polyDefDef(tpd.scala:235)
at dotty.tools.dotc.ast.tpd$.DefDef(tpd.scala:225)
at dotty.tools.dotc.ast.tpd$.DefDef(tpd.scala:222)
at dotty.tools.dotc.tastyreflect.FromSymbol$.defDefFromSym(FromSymbol.scala:46)
at dotty.tools.dotc.tastyreflect.FromSymbol$.definitionFromSym(FromSymbol.scala:19)
at dotty.tools.dotc.tastyreflect.FromSymbol$.$anonfun$5(FromSymbol.scala:35)
at scala.collection.immutable.List.map(List.scala:250)
at dotty.tools.dotc.tastyreflect.FromSymbol$.classDef(FromSymbol.scala:35)
at dotty.tools.dotc.tastyreflect.FromSymbol$.definitionFromSym(FromSymbol.scala:16)
at dotty.tools.dotc.tastyreflect.ReflectionCompilerInterface.Symbol_tree(ReflectionCompilerInterface.scala:1672)
at dotty.tools.dotc.tastyreflect.ReflectionCompilerInterface.Symbol_tree(ReflectionCompilerInterface.scala:1671)
at scala.tasty.Reflection$SymbolOps$.tree(Reflection.scala:2161)
at izumi.reflect.dottyreflection.Inspector.symbolToNameReference(Inspect.scala:84)
at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspect.scala:66)
at izumi.reflect.dottyreflection.Inspector.inspectTree(Inspect.scala:39)
at izumi.reflect.dottyreflection.Inspector.buildTypeRef(Inspect.scala:29)
at izumi.reflect.dottyreflection.Inspect$.inspectAny(Inspect.scala:9)
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:567)
at dotty.tools.dotc.transform.Splicer$Interpreter.interpretedStaticMethodCall$$anonfun$2$$anonfun$1(Splicer.scala:320)
at dotty.tools.dotc.transform.Splicer$Interpreter.stopIfRuntimeException(Splicer.scala:380)
at dotty.tools.dotc.transform.Splicer$Interpreter.interpretedStaticMethodCall$$anonfun$1(Splicer.scala:320)
at dotty.tools.dotc.transform.Splicer$Interpreter.interpretTree(Splicer.scala:245)
at dotty.tools.dotc.transform.Splicer$Interpreter.interpretTree$$anonfun$4(Splicer.scala:265)
at dotty.tools.dotc.transform.Splicer$.$anonfun$2(Splicer.scala:49)
at scala.Option.fold(Option.scala:263)
at dotty.tools.dotc.transform.Splicer$.splice(Splicer.scala:49)
at dotty.tools.dotc.typer.Inliner.dotty$tools$dotc$typer$Inliner$$expandMacro(Inliner.scala:1430)
at dotty.tools.dotc.typer.Inliner$InlineTyper.typedApply(Inliner.scala:1258)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2345)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2404)
at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:124)
at dotty.tools.dotc.typer.Typer.op$1(Typer.scala:2443)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2452)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2455)
at dotty.tools.dotc.typer.ReTyper.typedTyped(ReTyper.scala:60)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2350)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2404)
at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:124)
at dotty.tools.dotc.typer.Typer.op$1(Typer.scala:2443)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2452)
at dotty.tools.dotc.typer.Typer.op$1(Typer.scala:2439)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2452)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2455)
at dotty.tools.dotc.typer.Inliner.op$1(Inliner.scala:753)
at dotty.tools.dotc.typer.Inliner.inlined(Inliner.scala:772)
at dotty.tools.dotc.typer.Inliner$.inlineCall(Inliner.scala:115)
at dotty.tools.dotc.typer.Typer.adaptNoArgsOther$4(Typer.scala:3084)
at dotty.tools.dotc.typer.Typer.adaptNoArgs$1(Typer.scala:3181)
at dotty.tools.dotc.typer.Typer.adapt1(Typer.scala:3389)
at dotty.tools.dotc.typer.Typer.op$3(Typer.scala:2777)
at dotty.tools.dotc.typer.Typer.adapt(Typer.scala:2778)
at dotty.tools.dotc.typer.Typer.op$1(Typer.scala:2443)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2452)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2455)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:2566)
at dotty.tools.dotc.typer.Typer.typedBlock(Typer.scala:854)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2353)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2404)
at dotty.tools.dotc.typer.ProtoTypes$FunProto.$anonfun$2(ProtoTypes.scala:337)
at dotty.tools.dotc.typer.ProtoTypes$FunProto.cacheTypedArg(ProtoTypes.scala:293)
at dotty.tools.dotc.typer.ProtoTypes$FunProto.typedArg(ProtoTypes.scala:338)
at dotty.tools.dotc.typer.Applications$ApplyToUntyped.typedArg(Applications.scala:795)
at dotty.tools.dotc.typer.Applications$ApplyToUntyped.typedArg(Applications.scala:795)
at dotty.tools.dotc.typer.Applications$Application.addTyped$1(Applications.scala:530)
at dotty.tools.dotc.typer.Applications$Application.matchArgs(Applications.scala:599)
at dotty.tools.dotc.typer.Applications$Application.init(Applications.scala:355)
at dotty.tools.dotc.typer.Applications$TypedApply.<init>(Applications.scala:692)
at dotty.tools.dotc.typer.Applications$ApplyToUntyped.<init>(Applications.scala:794)
at dotty.tools.dotc.typer.Applications.ApplyTo(Applications.scala:997)
at dotty.tools.dotc.typer.Typer.ApplyTo(Typer.scala:85)
at dotty.tools.dotc.typer.Applications.simpleApply$1(Applications.scala:864)
at dotty.tools.dotc.typer.Applications.realApply$5$$anonfun$4(Applications.scala:925)
at dotty.tools.dotc.typer.Typer.tryEither(Typer.scala:2574)
at dotty.tools.dotc.typer.Applications.realApply$1(Applications.scala:936)
at dotty.tools.dotc.typer.Applications.typedApply(Applications.scala:972)
at dotty.tools.dotc.typer.Typer.typedApply(Typer.scala:85)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2345)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2404)
at dotty.tools.dotc.typer.Typer.op$1(Typer.scala:2443)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2452)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2455)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:2566)
at dotty.tools.dotc.typer.Typer.typedBlock(Typer.scala:854)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2353)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2404)
at dotty.tools.dotc.typer.Typer.op$1(Typer.scala:2443)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2452)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2455)
at dotty.tools.dotc.typer.Namer.typedAheadExpr$$anonfun$1(Namer.scala:1329)
at dotty.tools.dotc.typer.Namer.typedAhead(Namer.scala:1319)
at dotty.tools.dotc.typer.Namer.typedAheadExpr(Namer.scala:1329)
at dotty.tools.dotc.typer.Namer.rhsType$2(Namer.scala:1463)
at dotty.tools.dotc.typer.Namer.cookedRhsType$1(Namer.scala:1474)
at dotty.tools.dotc.typer.Namer.lhsType$1(Namer.scala:1475)
at dotty.tools.dotc.typer.Namer.inferredType$1(Namer.scala:1486)
at dotty.tools.dotc.typer.Namer.valOrDefDefSig(Namer.scala:1494)
at dotty.tools.dotc.typer.Namer.defDefSig(Namer.scala:1567)
at dotty.tools.dotc.typer.Namer$Completer.typeSig(Namer.scala:813)
at dotty.tools.dotc.typer.Namer$Completer.completeInCreationContext(Namer.scala:930)
at dotty.tools.dotc.typer.Namer$Completer.complete(Namer.scala:841)
at dotty.tools.dotc.core.SymDenotations$SymDenotation.completeFrom(SymDenotations.scala:259)
at dotty.tools.dotc.core.Denotations$Denotation.completeInfo$1(Denotations.scala:186)
at dotty.tools.dotc.core.Denotations$Denotation.info(Denotations.scala:188)
at dotty.tools.dotc.ast.tpd$.polyDefDef(tpd.scala:235)
at dotty.tools.dotc.ast.tpd$.DefDef(tpd.scala:225)
at dotty.tools.dotc.ast.tpd$.DefDef(tpd.scala:222)
at dotty.tools.dotc.tastyreflect.FromSymbol$.defDefFromSym(FromSymbol.scala:46)
at dotty.tools.dotc.tastyreflect.FromSymbol$.definitionFromSym(FromSymbol.scala:19)
at dotty.tools.dotc.tastyreflect.FromSymbol$.$anonfun$5(FromSymbol.scala:35)
at scala.collection.immutable.List.map(List.scala:250)
at dotty.tools.dotc.tastyreflect.FromSymbol$.classDef(FromSymbol.scala:35)
at dotty.tools.dotc.tastyreflect.FromSymbol$.definitionFromSym(FromSymbol.scala:16)
at dotty.tools.dotc.tastyreflect.ReflectionCompilerInterface.Symbol_tree(ReflectionCompilerInterface.scala:1672)
at dotty.tools.dotc.tastyreflect.ReflectionCompilerInterface.Symbol_tree(ReflectionCompilerInterface.scala:1671)
at scala.tasty.Reflection$SymbolOps$.tree(Reflection.scala:2161)
at izumi.reflect.dottyreflection.Inspector.symbolToNameReference(Inspect.scala:84)
at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspect.scala:66)
at izumi.reflect.dottyreflection.Inspector.inspectTree(Inspect.scala:39)
at izumi.reflect.dottyreflection.Inspector.buildTypeRef(Inspect.scala:29)
at izumi.reflect.dottyreflection.Inspect$.inspectAny(Inspect.scala:9)
inspect[Foo]
package test
import izumi.reflect.dottyreflection.Inspect.inspect
object Test2 extends App {
// local class not ok
locally {
class Bar
inspect[Bar]
}
}
Error:(10, 12) Exception occurred while executing macro expansion.
java.lang.RuntimeException: Type, UNSUPPORTED: class dotty.tools.dotc.core.Types$NoType$ - NoType
at izumi.reflect.dottyreflection.Inspector.inspectType(Inspect.scala:58)
at izumi.reflect.dottyreflection.Inspector.inspectTree(Inspect.scala:37)
at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspect.scala:72)
at izumi.reflect.dottyreflection.Inspector.symbolToNameReference(Inspect.scala:86)
at izumi.reflect.dottyreflection.Inspector.inspectSymbol(Inspect.scala:66)
at izumi.reflect.dottyreflection.Inspector.inspectTree(Inspect.scala:39)
at izumi.reflect.dottyreflection.Inspector.buildTypeRef(Inspect.scala:29)
at izumi.reflect.dottyreflection.Inspect$.inspectAny(Inspect.scala:9)
inspect[Bar]
package izumi.reflect.dottyreflection
import scala.quoted.{Expr, QuoteContext}
object Inspect {
inline def inspect[T <: AnyKind]: String = ${ inspectAny[T] }
def inspectAny[T <: AnyKind : quoted.Type](using qctx0: QuoteContext): Expr[String] = {
val ref = new Inspector().buildTypeRef[T]
println(s"result: $ref")
Expr(ref.toString)
}
}
final case class NameReference(ref: String, prefix: Option[NameReference]) {
override def toString: String = prefix.fold("")(p => s"$p::") + ref
}
class Inspector(implicit qctx: QuoteContext) {
import qctx.tasty._
protected def log(s: String) = {
println(" -> " + s)
}
def buildTypeRef[T <: AnyKind](using tpe: quoted.Type[T]): NameReference = {
val uns = tpe.unseal
log(s" -------- about to inspect ${tpe} --------")
val v = inspectTree(uns)
log(s" -------- done inspecting ${tpe} --------")
v
}
private def inspectTree(tpeTree: TypeTree): NameReference = {
log(s"INSPECT: $tpeTree: ${tpeTree.getClass}")
if (tpeTree.symbol.isNoSymbol) {
inspectType(tpeTree.tpe)
} else {
inspectSymbol(tpeTree.symbol)
}
}
private def inspectType(tpe: Type): NameReference = {
log(s"INSPECT: type `$tpe`")
tpe match {
case r: TypeRef =>
inspectSymbol(r.typeSymbol)
case a: AnnotatedType =>
inspectType(a.underlying)
case lazyref if lazyref.getClass.getName.contains("LazyRef") => // upstream bug seems like
log(s"LazyRef occured $lazyref")
throw new RuntimeException(s"LazyRef occured $lazyref")
case o =>
log(s"Type, UNSUPPORTED: ${o.getClass} - $o")
throw new RuntimeException(s"Type, UNSUPPORTED: ${o.getClass} - $o")
}
}
private def inspectSymbol(symbol: Symbol): NameReference = {
log(s"INSPECT: symbol `$symbol`")
symbol.tree match {
case c: ClassDef =>
symbolToNameReference(symbol)
case t: TypeDef =>
inspectTree(t.rhs.asInstanceOf[TypeTree])
case v: ValDef =>
inspectTree(v.tpt)
case o =>
log(s"SYMBOL TREE, UNSUPPORTED: $o")
throw new RuntimeException(s"SYMBOL TREE, UNSUPPORTED: ${o.getClass} - $o")
}
}
private def symbolToNameReference(sym: Symbol): NameReference = {
val prefix = if (sym.maybeOwner.isNoSymbol) {
None
} else {
sym.owner.tree match {
case _: PackageDef => None
case _ => Some(inspectSymbol(sym.maybeOwner))
}
}
NameReference(sym.fullName, prefix)
}
}
@nicolasstucki : did you get a chance to look at this issue?
Unfortunately, I did not
This is still affecting users of ZIO on Scala 3 as of 0.27, there was a question on discord today from user aappddeevv bumping into this issue: https://discordapp.com/channels/629491597070827530/630498701860929559/763866388367671347
Bar is the local dummy, a marker val that lets us know that this is locally defined in the constructor of Test2. This dummy can be identified with isLocalDummy.Re (2): Seems like we need a "localDummyIdentifier" thingy, something similar to FQN but considering scoping. So we may distinguish different Bars in local contexts.
Previously we've been using prefixes, which may be logically incorrect but better than being unable to identify context at all.
Could you suggest something?
@pshirshov
Previously we've been using prefixes, which may be logically incorrect
Could you please elaborate, what's wrong with prefixes?
Typer (see #7825). Not sure how to avoid it for transparent inline yet (seems to be the same issue as in #7592).Could you please elaborate, what's wrong with prefixes?
You cannot disambiguate these classes:
locally {
class Bar
}
locally {
class Bar
}
Current izumi-reflect implementation will consider their typetags equal.
In this particular case, you should be able to distinguish them by their symbol.
We need a serializable identifier though. Anyway, that's different from this issue and actually not that important.
Maybe you can use their positions to serialize them when they are local.
Yup, that's one of the options.
Note that positions is unavailable for a symbols coming from another package.
And it is not that simple to distinguish between this two cases:
class T { class X }
val a = new T // a.X is accessible from other packages
val b = println({ class X; "hi" }) // b.X isn't accessible from the outside of this block
So I'm not sure if it is possible to reliably serialize identifiers regardless of where they are inspected/come from.
Usually, local definitions are represented with some special notation and a unique local id. This special notation tells us that it is local and hence not accessible from outside. If you want to serialize a symbol with a string name you may take inspiration from the semanticdb format https://scalameta.org/docs/semanticdb/specification.html#symbol.
Current relevant PR: lampepfl/dotty#9984 - this should fix the principal issue when merged (the interference between type inference and type info available in blackbox macros)