Skip to content

Commit bb5c098

Browse files
committed
Dealias type references when healing types in quotes
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
1 parent ce65296 commit bb5c098

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)