@@ -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)
@@ -118,7 +120,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
118
120
if body.isTerm then
119
121
// `quoted.runtime.Expr.quote[T](<body>)` --> `quoted.runtime.Expr.quote[T2](<body2>)`
120
122
val TypeApply (fun, targs) = quote.fun: @ unchecked
121
- val targs2 = targs.map(targ => TypeTree (healTypeOfTerm (quote.fun.srcPos)(stripAnnotsDeep(targ.tpe))))
123
+ val targs2 = targs.map(targ => TypeTree (healType (quote.fun.srcPos)(stripAnnotsDeep(targ.tpe))))
122
124
cpy.Apply (quote)(cpy.TypeApply (quote.fun)(fun, targs2), body2 :: Nil )
123
125
else
124
126
val quotes = quote.args.mapConserve(transform)
@@ -193,61 +195,57 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
193
195
def apply (tp : Type ): Type =
194
196
tp match
195
197
case tp : TypeRef =>
196
- tp.prefix match
197
- case NoPrefix if level > levelOf(tp.symbol) && ! tp.typeSymbol.hasAnnotation(defn.QuotedRuntime_SplicedTypeAnnot ) =>
198
- tryHealTypeOfType(tp.symbol, tp, pos)
199
- case prefix : ThisType if ! tp.symbol.isStatic && level > levelOf(prefix.cls) =>
200
- tryHealTypeOfType(tp.symbol, tp, pos)
201
- case prefix : TermRef if tp.symbol.isTypeSplice =>
202
- prefix.symbol.info.argInfos match
203
- case (tb : TypeBounds ) :: _ =>
204
- report.error(em " Cannot splice $tp because it is a wildcard type " , pos)
205
- case _ =>
206
- // Heal explicit type splice in the code
207
- if level > 0 then getQuoteTypeTags.getTagRef(prefix) else tp
208
- case prefix : TermRef if ! prefix.symbol.isStatic && level > levelOf(prefix.symbol) =>
209
- tryHealTypeOfType(prefix.symbol, tp, pos)
210
- case _ =>
211
- mapOver(tp)
198
+ healTypeRef(tp)
212
199
case tp @ TermRef (NoPrefix , _) if ! tp.symbol.isStatic && level > levelOf(tp.symbol) =>
213
200
levelError(tp.symbol, tp, pos)
214
- case tp : ThisType if level != - 1 && level != levelOf(tp.cls) =>
215
- levelError(tp.cls, tp, pos)
216
201
case tp : AnnotatedType =>
217
202
val newAnnotTree = transform(tp.annot.tree)
218
203
derivedAnnotatedType(tp, apply(tp.parent), tp.annot.derivedAnnotation(newAnnotTree))
219
204
case _ =>
220
205
mapOver(tp)
221
206
222
- /** Try to dealias or heal reference to type `T` used in a higher level than its definition.
223
- * Returns a reference to a type tag generated by `QuoteTypeTags` that contains a
224
- * reference to a type alias containing the equivalent of `${summon[quoted.Type[T]]}`.
225
- * Emits and error if `T` cannot be healed and returns `T`.
226
- */
227
- private def tryHealTypeOfType (sym : Symbol , tp : TypeRef , pos : SrcPos )(using Context ): Type = {
207
+ private def healTypeRef (tp : TypeRef ): Type =
208
+ tp.prefix match
209
+ case prefix : TermRef if tp.symbol.isTypeSplice =>
210
+ checkNotWildcardSplice(tp)
211
+ if level == 0 then tp else getQuoteTypeTags.getTagRef(prefix)
212
+ case prefix : TermRef if ! prefix.symbol.isStatic && level > levelOf(prefix.symbol) =>
213
+ dealiasAndTryHeal(prefix.symbol, tp, pos)
214
+ case NoPrefix if level > levelOf(tp.symbol) && ! tp.typeSymbol.hasAnnotation(defn.QuotedRuntime_SplicedTypeAnnot ) =>
215
+ dealiasAndTryHeal(tp.symbol, tp, pos)
216
+ case prefix : ThisType if level > levelOf(prefix.cls) && ! tp.symbol.isStatic =>
217
+ dealiasAndTryHeal(tp.symbol, tp, pos)
218
+ case _ =>
219
+ mapOver(tp)
220
+
221
+ private def dealiasAndTryHeal (sym : Symbol , tp : TypeRef , pos : SrcPos )(using Context ): Type =
228
222
val tp1 = tp.dealias
229
223
if tp1 != tp then apply(tp1)
230
224
else tryHeal(tp.symbol, tp, pos)
231
- }
232
- }
233
225
234
- /** Check phase consistency of terms and heal inconsistent type references. */
235
- private def healTypeOfTerm (pos : SrcPos )(using Context ) = new TypeMap {
236
- def apply (tp : Type ): Type =
237
- tp match
238
- case tp @ TypeRef (NoPrefix , _) if level > levelOf(tp.symbol) =>
239
- tryHeal(tp.symbol, tp, pos)
240
- case tp @ TermRef (NoPrefix , _) if ! tp.symbol.isStatic && level != levelOf(tp.symbol) =>
241
- levelError(tp.symbol, tp, pos)
242
- case tp : ThisType if level != - 1 && level != levelOf(tp.cls) =>
243
- levelError(tp.cls, tp, pos)
244
- case tp : AnnotatedType =>
245
- derivedAnnotatedType(tp, apply(tp.parent), tp.annot)
226
+ private def checkNotWildcardSplice (splice : TypeRef )(using Context ): Unit =
227
+ splice.prefix.termSymbol.info.argInfos match
228
+ case (tb : TypeBounds ) :: _ => report.error(em " Cannot splice $splice because it is a wildcard type " , pos)
246
229
case _ =>
247
- if tp.typeSymbol.is(Package ) then tp
248
- else mapOver(tp)
249
230
}
250
231
232
+ /** Check level consistency of terms references */
233
+ private def checkLevelConsistency (tree : Ident | This )(using Context ): Unit =
234
+ new TypeTraverser {
235
+ def traverse (tp : Type ): Unit =
236
+ tp match
237
+ case tp @ TermRef (NoPrefix , _) if ! tp.symbol.isStatic && level != levelOf(tp.symbol) =>
238
+ levelError(tp.symbol, tp, tree.srcPos)
239
+ case tp : ThisType if level != - 1 && level != levelOf(tp.cls) =>
240
+ levelError(tp.cls, tp, tree.srcPos)
241
+ case tp : AnnotatedType =>
242
+ traverse(tp.parent)
243
+ case _ if tp.typeSymbol.is(Package ) =>
244
+ // OK
245
+ case _ =>
246
+ traverseChildren(tp)
247
+ }.traverse(tree.tpe)
248
+
251
249
/** Try to heal reference to type `T` used in a higher level than its definition.
252
250
* Returns a reference to a type tag generated by `QuoteTypeTags` that contains a
253
251
* reference to a type alias containing the equivalent of `${summon[quoted.Type[T]]}`.
0 commit comments