Skip to content

Commit 28676ae

Browse files
Dealias type references when healing types in quotes (#17049)
We where only doing the dealiasing if the type had no prefix but missed it if the type reference was on some path. Fixes #17037
2 parents fd91ce1 + bb5c098 commit 28676ae

File tree

4 files changed

+39
-5
lines changed

4 files changed

+39
-5
lines changed

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

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,9 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
192192
case tp: TypeRef =>
193193
tp.prefix match
194194
case NoPrefix if level > levelOf(tp.symbol) && !tp.typeSymbol.hasAnnotation(defn.QuotedRuntime_SplicedTypeAnnot) =>
195-
val tp1 = tp.dealias
196-
if tp1 != tp then apply(tp1)
197-
else tryHeal(tp.symbol, tp, pos)
195+
tryHealTypeOfType(tp.symbol, tp, pos)
198196
case prefix: ThisType if !tp.symbol.isStatic && level > levelOf(prefix.cls) =>
199-
tryHeal(tp.symbol, tp, pos)
197+
tryHealTypeOfType(tp.symbol, tp, pos)
200198
case prefix: TermRef if tp.symbol.isTypeSplice =>
201199
prefix.symbol.info.argInfos match
202200
case (tb: TypeBounds) :: _ =>
@@ -205,7 +203,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
205203
// Heal explicit type splice in the code
206204
if level > 0 then getQuoteTypeTags.getTagRef(prefix) else tp
207205
case prefix: TermRef if !prefix.symbol.isStatic && level > levelOf(prefix.symbol) =>
208-
tryHeal(prefix.symbol, tp, pos)
206+
tryHealTypeOfType(prefix.symbol, tp, pos)
209207
case _ =>
210208
mapOver(tp)
211209
case tp @ TermRef(NoPrefix, _) if !tp.symbol.isStatic && level > levelOf(tp.symbol) =>
@@ -217,6 +215,17 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
217215
derivedAnnotatedType(tp, apply(tp.parent), tp.annot.derivedAnnotation(newAnnotTree))
218216
case _ =>
219217
mapOver(tp)
218+
219+
/** Try to dealias or heal reference to type `T` used in a higher level than its definition.
220+
* Returns a reference to a type tag generated by `QuoteTypeTags` that contains a
221+
* reference to a type alias containing the equivalent of `${summon[quoted.Type[T]]}`.
222+
* Emits and error if `T` cannot be healed and returns `T`.
223+
*/
224+
private def tryHealTypeOfType(sym: Symbol, tp: TypeRef, pos: SrcPos)(using Context): Type = {
225+
val tp1 = tp.dealias
226+
if tp1 != tp then apply(tp1)
227+
else tryHeal(tp.symbol, tp, pos)
228+
}
220229
}
221230

222231
/** Check phase consistency of terms and heal inconsistent type references. */

tests/pos-macros/i17037.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import scala.quoted.*
2+
3+
class Foo:
4+
type Bar = Int
5+
6+
def macroImpl(using Quotes) =
7+
val foo = new Foo
8+
Type.of[foo.Bar]

tests/pos-macros/i17037b.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import scala.quoted.*
2+
3+
class Foo:
4+
type Bar = Int
5+
6+
def macroImpl(using Quotes) =
7+
val foo = Foo()
8+
Type.of[foo.Bar] match
9+
case '[foo.Bar] => '{true}
10+
case _ => '{false}

tests/pos-macros/i17037c.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import scala.quoted.*
2+
3+
class Foo:
4+
type Bar = Int
5+
def macroImpl(using Quotes) =
6+
val foo = new Foo
7+
Type.of[this.Bar]

0 commit comments

Comments
 (0)