@@ -61,24 +61,26 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
61
61
super .transform(tree)
62
62
else tree match {
63
63
64
- case _ : TypeTree | _ : RefTree if tree.isType =>
64
+ case _ : TypeTree | _ : RefTree if tree.isType =>
65
65
val healedType = healType(tree.srcPos)(tree.tpe)
66
66
if healedType == tree.tpe then tree
67
67
else TypeTree (healedType).withSpan(tree.span)
68
+ case tree : Ident if isWildcardArg(tree) =>
69
+ tree.withType(healType(tree.srcPos)(tree.tpe))
70
+ case tree : Ident => // this is a term Ident
71
+ checkLevelConsistency(tree)
72
+ tree
73
+ case tree : This =>
74
+ checkLevelConsistency(tree)
75
+ tree
68
76
case _ : AppliedTypeTree =>
69
77
super .transform(tree) match
70
78
case tree1 : AppliedTypeTree if tree1 ne tree =>
71
79
// propagate healed types
72
80
tree1.withType(tree1.tpt.tpe.appliedTo(tree1.args.map(_.tpe)))
73
81
case tree1 => tree1
74
-
75
- case _ : Ident | _ : This =>
76
- tree.withType(healTypeOfTerm(tree.srcPos)(tree.tpe))
77
-
78
- // Remove inline defs in quoted code. Already fully inlined.
79
82
case tree : DefDef if tree.symbol.is(Inline ) && level > 0 =>
80
- EmptyTree
81
-
83
+ EmptyTree // Remove inline defs in quoted code. Already fully inlined.
82
84
case tree : ValOrDefDef =>
83
85
checkAnnotations(tree)
84
86
healInfo(tree, tree.tpt.srcPos)
@@ -88,7 +90,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
88
90
healInfo(tree, tree.srcPos)
89
91
super .transform(tree)
90
92
case tree : UnApply =>
91
- super .transform(tree).withType(healTypeOfTerm (tree.srcPos)(tree.tpe))
93
+ super .transform(tree).withType(healType (tree.srcPos)(tree.tpe))
92
94
case tree : TypeDef if tree.symbol.is(Case ) && level > 0 =>
93
95
report.error(reporting.CaseClassInInlinedCode (tree), tree)
94
96
super .transform(tree)
@@ -115,7 +117,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
115
117
if body.isTerm then
116
118
// `quoted.runtime.Expr.quote[T](<body>)` --> `quoted.runtime.Expr.quote[T2](<body2>)`
117
119
val TypeApply (fun, targs) = quote.fun: @ unchecked
118
- val targs2 = targs.map(targ => TypeTree (healTypeOfTerm (quote.fun.srcPos)(targ.tpe)))
120
+ val targs2 = targs.map(targ => TypeTree (healType (quote.fun.srcPos)(targ.tpe)))
119
121
cpy.Apply (quote)(cpy.TypeApply (quote.fun)(fun, targs2), body2 :: Nil )
120
122
else
121
123
val quotes = quote.args.mapConserve(transform)
@@ -190,61 +192,57 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
190
192
def apply (tp : Type ): Type =
191
193
tp match
192
194
case tp : TypeRef =>
193
- tp.prefix match
194
- case NoPrefix if level > levelOf(tp.symbol) && ! tp.typeSymbol.hasAnnotation(defn.QuotedRuntime_SplicedTypeAnnot ) =>
195
- tryHealTypeOfType(tp.symbol, tp, pos)
196
- case prefix : ThisType if ! tp.symbol.isStatic && level > levelOf(prefix.cls) =>
197
- tryHealTypeOfType(tp.symbol, tp, pos)
198
- case prefix : TermRef if tp.symbol.isTypeSplice =>
199
- prefix.symbol.info.argInfos match
200
- case (tb : TypeBounds ) :: _ =>
201
- report.error(em " Cannot splice $tp because it is a wildcard type " , pos)
202
- case _ =>
203
- // Heal explicit type splice in the code
204
- if level > 0 then getQuoteTypeTags.getTagRef(prefix) else tp
205
- case prefix : TermRef if ! prefix.symbol.isStatic && level > levelOf(prefix.symbol) =>
206
- tryHealTypeOfType(prefix.symbol, tp, pos)
207
- case _ =>
208
- mapOver(tp)
195
+ healTypeRef(tp)
209
196
case tp @ TermRef (NoPrefix , _) if ! tp.symbol.isStatic && level > levelOf(tp.symbol) =>
210
197
levelError(tp.symbol, tp, pos)
211
- case tp : ThisType if level != - 1 && level != levelOf(tp.cls) =>
212
- levelError(tp.cls, tp, pos)
213
198
case tp : AnnotatedType =>
214
199
val newAnnotTree = transform(tp.annot.tree)
215
200
derivedAnnotatedType(tp, apply(tp.parent), tp.annot.derivedAnnotation(newAnnotTree))
216
201
case _ =>
217
202
mapOver(tp)
218
203
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 = {
204
+ private def healTypeRef (tp : TypeRef ): Type =
205
+ tp.prefix match
206
+ case prefix : TermRef if tp.symbol.isTypeSplice =>
207
+ checkNotWildcardSplice(tp)
208
+ if level == 0 then tp else getQuoteTypeTags.getTagRef(prefix)
209
+ case prefix : TermRef if ! prefix.symbol.isStatic && level > levelOf(prefix.symbol) =>
210
+ dealiasAndTryHeal(prefix.symbol, tp, pos)
211
+ case NoPrefix if level > levelOf(tp.symbol) && ! tp.typeSymbol.hasAnnotation(defn.QuotedRuntime_SplicedTypeAnnot ) =>
212
+ dealiasAndTryHeal(tp.symbol, tp, pos)
213
+ case prefix : ThisType if level > levelOf(prefix.cls) && ! tp.symbol.isStatic =>
214
+ dealiasAndTryHeal(tp.symbol, tp, pos)
215
+ case _ =>
216
+ mapOver(tp)
217
+
218
+ private def dealiasAndTryHeal (sym : Symbol , tp : TypeRef , pos : SrcPos )(using Context ): Type =
225
219
val tp1 = tp.dealias
226
220
if tp1 != tp then apply(tp1)
227
221
else tryHeal(tp.symbol, tp, pos)
228
- }
229
- }
230
222
231
- /** Check phase consistency of terms and heal inconsistent type references. */
232
- private def healTypeOfTerm (pos : SrcPos )(using Context ) = new TypeMap {
233
- def apply (tp : Type ): Type =
234
- tp match
235
- case tp @ TypeRef (NoPrefix , _) if level > levelOf(tp.symbol) =>
236
- tryHeal(tp.symbol, tp, pos)
237
- case tp @ TermRef (NoPrefix , _) if ! tp.symbol.isStatic && level != levelOf(tp.symbol) =>
238
- levelError(tp.symbol, tp, pos)
239
- case tp : ThisType if level != - 1 && level != levelOf(tp.cls) =>
240
- levelError(tp.cls, tp, pos)
241
- case tp : AnnotatedType =>
242
- derivedAnnotatedType(tp, apply(tp.parent), tp.annot)
223
+ private def checkNotWildcardSplice (splice : TypeRef )(using Context ): Unit =
224
+ splice.prefix.termSymbol.info.argInfos match
225
+ case (tb : TypeBounds ) :: _ => report.error(em " Cannot splice $splice because it is a wildcard type " , pos)
243
226
case _ =>
244
- if tp.typeSymbol.is(Package ) then tp
245
- else mapOver(tp)
246
227
}
247
228
229
+ /** Check level consistency of terms references */
230
+ private def checkLevelConsistency (tree : Ident | This )(using Context ): Unit =
231
+ new TypeTraverser {
232
+ def traverse (tp : Type ): Unit =
233
+ tp match
234
+ case tp @ TermRef (NoPrefix , _) if ! tp.symbol.isStatic && level != levelOf(tp.symbol) =>
235
+ levelError(tp.symbol, tp, tree.srcPos)
236
+ case tp : ThisType if level != - 1 && level != levelOf(tp.cls) =>
237
+ levelError(tp.cls, tp, tree.srcPos)
238
+ case tp : AnnotatedType =>
239
+ traverse(tp.parent)
240
+ case _ if tp.typeSymbol.is(Package ) =>
241
+ // OK
242
+ case _ =>
243
+ traverseChildren(tp)
244
+ }.traverse(tree.tpe)
245
+
248
246
/** Try to heal reference to type `T` used in a higher level than its definition.
249
247
* Returns a reference to a type tag generated by `QuoteTypeTags` that contains a
250
248
* reference to a type alias containing the equivalent of `${summon[quoted.Type[T]]}`.
0 commit comments