You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Jun 5, 2023. It is now read-only.
Creating an instance of a given Type[A] enriched with helper traits.
This functionality is necessary for porting Airframe DI, a dependency injection library (https://wvlet.org/airframe/docs/airframe), to Scala 3. Scala 2 has an untyped quasiquotes, so we can generate new A with ... { ... }. Scala 3 macros has strict type checking, so if A might not be able to instantiate, it reject any code generation for new A { ... } even when A is just a trait.
Minimized code
scala>importscala.quoted._
scala>traitLogSupport// defined trait LogSupport
scala>inlinedefmk[A] = { newAwithLogSupport {} }
1|inline defmk[A] = { newAwithLogSupport {} }
|^|A is not a classtype
Using Scala 3 macro show the same error:
defnewInstanceImpl[A](using quotes:Quotes, t:Type[A]):Expr[A] = {
'{
newA {} // Compile error: A is not a class type
}
}
Output
The compiler internally generates an anonymous class if A is a trait:
vale='{
traitA; newA {}
}
pritnln(e.show)
{
finalclass$anon() extendsA
(new $anon():A)
}
But if type A is given as Type[A] to Scala 3 macros or inline methods, even though Type[A] is referencing a trait, we cannot generate code equivalent to new A {}.
I've added a code to dotty to show the stack trace around this compile error. It seems Type.underlyingClassRef called at checkClassType failed to resolve the anonymous class generated by Dotty (3.0.0-M3):
[error] |A is not a classtype:
[error] |java.lang.Throwable
[error] | at dotty.tools.dotc.typer.Checking.checkClassType(Checking.scala:762)
[error] | at dotty.tools.dotc.typer.Checking.checkClassType$(Checking.scala:653)
[error] | at dotty.tools.dotc.typer.Typer.checkClassType(Typer.scala:101)
[error] | at dotty.tools.dotc.typer.Namer$ClassCompleter.checkedParentType$2(Namer.scala:1180)
[error] | at dotty.tools.dotc.typer.Namer$ClassCompleter.$anonfun$1(Namer.scala:1212)
[error] | at scala.collection.immutable.List.map(List.scala:246)
[error] | at dotty.tools.dotc.typer.Namer$ClassCompleter.completeInCreationContext(Namer.scala:1212)
[error] | at dotty.tools.dotc.typer.Namer$Completer.complete(Namer.scala:732)
[error] | at dotty.tools.dotc.core.SymDenotations$SymDenotation.completeFrom(SymDenotations.scala:166)
[error] | at dotty.tools.dotc.core.Denotations$Denotation.completeInfo$1(Denotations.scala:188)
[error] | at dotty.tools.dotc.core.Denotations$Denotation.info(Denotations.scala:190)
[error] | at dotty.tools.dotc.core.SymDenotations$SymDenotation.ensureCompleted(SymDenotations.scala:370)
[error] | at dotty.tools.dotc.typer.Typer.retrieveSym(Typer.scala:2473)
[error] | at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:2498)
[error] | at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2592)
[error] | at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2662)
[error] | at dotty.tools.dotc.typer.Typer.typed(Typer.scala:2666)
[error] | at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:2688)
[error] | at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:2738)
[error] | at dotty.tools.dotc.typer.Typer.typedBlockStats(Typer.scala:937)
Expectation
There should be a way to instantiate a Trait with inline methods and Scala 3 macros.
If A is not a trait, this compilation error is valid. We need a workaround if A is safe to instantiate when an anonymous class that extends A will be generated.
As a workaround, I've also tried to rewriting the AST using TreeMap by creating a concrete trait (e.g., trait X; new X{}, then rewrite X to A), but new X {} code will generate Template node, which is not yet exposed to Reflect API TreeMap doesn't traverse Template class scala/scala3#10931, so this approach also didn't work
The text was updated successfully, but these errors were encountered:
Use Case
Creating an instance of a given
Type[A]
enriched with helper traits.This functionality is necessary for porting Airframe DI, a dependency injection library (https://wvlet.org/airframe/docs/airframe), to Scala 3. Scala 2 has an untyped quasiquotes, so we can generate
new A with ... { ... }
. Scala 3 macros has strict type checking, so ifA
might not be able to instantiate, it reject any code generation fornew A { ... }
even whenA
is just a trait.Minimized code
Using Scala 3 macro show the same error:
Output
The compiler internally generates an anonymous class if A is a trait:
But if type A is given as
Type[A]
to Scala 3 macros or inline methods, even though Type[A] is referencing a trait, we cannot generate code equivalent tonew A {}
.I've added a code to dotty to show the stack trace around this compile error. It seems Type.underlyingClassRef called at checkClassType failed to resolve the anonymous class generated by Dotty (3.0.0-M3):
Expectation
q"""new ${t} {}""")
, so we can generate such a code at ease Support creating a new instance of a given Type[A] with Scala 3 macro #153trait X; new X{}
, then rewrite X to A), butnew X {}
code will generate Template node, which is not yet exposed to Reflect API TreeMap doesn't traverse Template class scala/scala3#10931, so this approach also didn't workThe text was updated successfully, but these errors were encountered: