Skip to content

Commit 3bb16f8

Browse files
Merge pull request #11590 from dotty-staging/fix-#11587-2
Heal type within quote internal encoding
2 parents 5e0100d + 8447d5a commit 3bb16f8

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ import scala.annotation.constructorOnly
3737
*
3838
* Type healing consists in transforming a phase inconsistent type `T` into a splice of `${summon[Type[T]]}`.
3939
*
40-
* As references to types do not necessarily have an assosiated tree it is not always possible to replace the types directly.
41-
* Instead we always generate a type alias for it and palce it at the start of the surounding quote. This also avoids duplication.
40+
* As references to types do not necessarily have an associated tree it is not always possible to replace the types directly.
41+
* Instead we always generate a type alias for it and place it at the start of the surrounding quote. This also avoids duplication.
4242
* For example:
4343
* '{
4444
* val x: List[T] = List[T]()
@@ -118,7 +118,13 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
118118
case Nil => body1
119119
case tags => tpd.Block(tags, body1).withSpan(body.span)
120120

121-
super.transformQuotation(body2, quote)
121+
quote match {
122+
case Apply(fn1 @ TypeApply(fn0, targs), _) =>
123+
val targs1 = targs.map(targ => TypeTree(healTypeOfTerm(fn1.srcPos)(targ.tpe)))
124+
cpy.Apply(quote)(cpy.TypeApply(fn1)(fn0, targs1), body2 :: Nil)
125+
case quote: TypeApply =>
126+
cpy.TypeApply(quote)(quote.fun, body2 :: Nil)
127+
}
122128
}
123129

124130
/** Transform splice
@@ -168,8 +174,8 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
168174
/** If the type refers to a locally defined symbol (either directly, or in a pickled type),
169175
* check that its staging level matches the current level.
170176
* - Static types and term are allowed at any level.
171-
* - If a type reference is used a higher level, then it is insosistent. Will atempt to heal before failing.
172-
* - If a term reference is used a different level, then it is insosistent.
177+
* - If a type reference is used a higher level, then it is inconsistent. Will attempt to heal before failing.
178+
* - If a term reference is used a different level, then it is inconsistent.
173179
*
174180
* If `T` is a reference to a type at the wrong level, try to heal it by replacing it with
175181
* a type tag of type `quoted.Type[T]`.
@@ -207,7 +213,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
207213
mapOver(tp)
208214
}
209215

210-
/** Check phase consistency of terms and heal incosistent type references. */
216+
/** Check phase consistency of terms and heal inconsistent type references. */
211217
private def healTypeOfTerm(pos: SrcPos)(using Context) = new TypeMap {
212218
def apply(tp: Type): Type =
213219
tp match
@@ -217,14 +223,16 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
217223
levelError(tp.symbol, tp, pos)
218224
case tp: ThisType if level != -1 && level != levelOf(tp.cls) =>
219225
levelError(tp.cls, tp, pos)
226+
case tp: AnnotatedType =>
227+
derivedAnnotatedType(tp, apply(tp.parent), tp.annot)
220228
case _ =>
221229
if tp.typeSymbol.is(Package) then tp
222230
else mapOver(tp)
223231
}
224232

225233
/** Try to heal reference to type `T` used in a higher level than its definition.
226234
* Returns a reference to a type tag generated by `QuoteTypeTags` that contains a
227-
* refercence to a type alias containing the equivalent of `${summon[quoted.Type[T]]}`.
235+
* reference to a type alias containing the equivalent of `${summon[quoted.Type[T]]}`.
228236
* Emits and error if `T` cannot be healed and returns `T`.
229237
*/
230238
protected def tryHeal(sym: Symbol, tp: TypeRef, pos: SrcPos)(using Context): TypeRef = {

tests/pos-macros/i11587.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import scala.quoted._
2+
class Foo:
3+
def foo[T: Type](using Quotes): Unit = '{ // level 1
4+
given Quotes = ???
5+
6+
Type.of[T]
7+
8+
'{ ??? : T } // level 2
9+
10+
'{ // level 2
11+
given Quotes = ???
12+
Type.of[T]
13+
'{ ??? : T } // level 3
14+
}
15+
}

0 commit comments

Comments
 (0)