@@ -74,8 +74,10 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
74
74
else tpd.Block (taggedTypes.getTypeTags, body1).withSpan(body.span)
75
75
76
76
quote match {
77
- case quote : Apply => cpy.Apply (quote)(transform(quote.fun), body2 :: Nil )
78
- case quote : TypeApply => cpy.TypeApply (quote)(transform(quote.fun), body2 :: Nil )
77
+ case quote @ Apply (tpApp @ TypeApply (fn, List (tpt)), _) =>
78
+ cpy.Apply (quote)(cpy.TypeApply (tpApp)(fn, List (transform(tpt)(ctx))), body2 :: Nil )
79
+ case quote : TypeApply =>
80
+ cpy.TypeApply (quote)(quote.fun, body2 :: Nil )
79
81
}
80
82
}
81
83
@@ -90,7 +92,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
90
92
case Apply (fun : TypeApply , _) if splice.isTerm =>
91
93
// Type of the splice itsel must also be healed
92
94
// internal.Quoted.expr[F[T]](... T ...) --> internal.Quoted.expr[F[$t]](... T ...)
93
- val tp = checkType(splice.sourcePos).apply(splice.tpe.widenTermRefExpr)
95
+ val tp = checkType(splice.sourcePos, adaptOnly = false ).apply(splice.tpe.widenTermRefExpr)
94
96
cpy.Apply (splice)(cpy.TypeApply (fun)(fun.fun, tpd.TypeTree (tp) :: Nil ), body1 :: Nil )
95
97
case splice : Select =>
96
98
val tagRef = getQuoteTypeTags.getTagRef(splice.qualifier.tpe.asInstanceOf [TermRef ])
@@ -106,36 +108,36 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
106
108
* `${implicitly[quoted.Type[T]]}`.
107
109
*/
108
110
protected def checkLevel (tree : Tree )(implicit ctx : Context ): Tree = {
109
- def checkTp (tp : Type ): Type = checkType(tree.sourcePos).apply(tp)
111
+ def checkTp (tp : Type , adaptOnly : Boolean ): Type = checkType(tree.sourcePos, adaptOnly ).apply(tp)
110
112
tree match {
111
113
case Quoted (_) | Spliced (_) =>
112
114
tree
113
115
case _ : This =>
114
- assert(checkSymLevel(tree.symbol, tree.tpe, tree.sourcePos).isEmpty)
116
+ assert(checkSymLevel(tree.symbol, tree.tpe, tree.sourcePos, adaptOnly = false ).isEmpty)
115
117
tree
116
118
case Ident (name) =>
117
119
if (name == nme.WILDCARD )
118
- untpd.Ident (name).withType(checkType(tree.sourcePos).apply(tree.tpe)).withSpan(tree.span)
120
+ untpd.Ident (name).withType(checkType(tree.sourcePos, adaptOnly = false ).apply(tree.tpe)).withSpan(tree.span)
119
121
else
120
- checkSymLevel(tree.symbol, tree.tpe, tree.sourcePos) match {
122
+ checkSymLevel(tree.symbol, tree.tpe, tree.sourcePos, adaptOnly = false ) match {
121
123
case Some (tpRef) => tpRef
122
124
case _ => tree
123
125
}
124
- case _ : TypeTree | _ : AppliedTypeTree | _ : Apply | _ : TypeApply | _ : UnApply | Select (_, OuterSelectName (_, _)) =>
125
- tree.withType(checkTp(tree.tpe))
126
+ case _ : TypeTree | _ : AppliedTypeTree | _ : Select | _ : Apply | _ : TypeApply | _ : UnApply | Select (_, OuterSelectName (_, _)) =>
127
+ tree.withType(checkTp(tree.tpe, adaptOnly = true ))
126
128
case _ : ValOrDefDef | _ : Bind =>
127
- tree.symbol.info = checkTp(tree.symbol.info)
129
+ tree.symbol.info = checkTp(tree.symbol.info, adaptOnly = false )
128
130
tree
129
131
case _ : Template =>
130
- checkTp(tree.symbol.owner.asClass.givenSelfType)
132
+ checkTp(tree.symbol.owner.asClass.givenSelfType, adaptOnly = false )
131
133
tree
132
134
case _ =>
133
135
tree
134
136
}
135
137
}
136
138
137
139
/** Check and heal all named types and this-types in a given type for phase consistency. */
138
- private def checkType (pos : SourcePosition )(implicit ctx : Context ): TypeMap = new TypeMap {
140
+ private def checkType (pos : SourcePosition , adaptOnly : Boolean )(implicit ctx : Context ): TypeMap = new TypeMap {
139
141
def apply (tp : Type ): Type = reporting.trace(i " check type level $tp at $level" ) {
140
142
tp match {
141
143
case tp : TypeRef if tp.symbol.isSplice =>
@@ -150,14 +152,14 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
150
152
getQuoteTypeTags.getTagRef(tp.prefix.asInstanceOf [TermRef ])
151
153
else tp
152
154
case tp : NamedType =>
153
- checkSymLevel(tp.symbol, tp, pos) match {
155
+ checkSymLevel(tp.symbol, tp, pos, adaptOnly ) match {
154
156
case Some (tpRef) => tpRef.tpe
155
157
case _ =>
156
158
if (tp.symbol.is(Param )) tp
157
159
else mapOver(tp)
158
160
}
159
161
case tp : ThisType =>
160
- assert(checkSymLevel(tp.cls, tp, pos).isEmpty)
162
+ assert(checkSymLevel(tp.cls, tp, pos, adaptOnly ).isEmpty)
161
163
mapOver(tp)
162
164
case tp : AnnotatedType =>
163
165
derivedAnnotatedType(tp, apply(tp.parent), tp.annot)
@@ -173,7 +175,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
173
175
* @return `None` if the phase is correct or cannot be healed
174
176
* `Some(tree)` with the `tree` of the healed type tree for `${implicitly[quoted.Type[T]]}`
175
177
*/
176
- private def checkSymLevel (sym : Symbol , tp : Type , pos : SourcePosition )(implicit ctx : Context ): Option [Tree ] = {
178
+ private def checkSymLevel (sym : Symbol , tp : Type , pos : SourcePosition , adaptOnly : Boolean )(implicit ctx : Context ): Option [Tree ] = {
177
179
/** Is a reference to a class but not `this.type` */
178
180
def isClassRef = sym.isClass && ! tp.isInstanceOf [ThisType ]
179
181
@@ -201,11 +203,13 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
201
203
else if (! sym.isStaticOwner && ! isClassRef)
202
204
tp match
203
205
case tp : TypeRef =>
204
- if levelOf(sym).getOrElse(0 ) < level then tryHeal(sym, tp, pos)
206
+ if levelOf(sym).getOrElse(0 ) < level then tryHeal(sym, tp, pos, adaptOnly )
205
207
else None
206
208
case _ =>
207
- levelError(sym, tp, pos, " " )
208
- else if (! sym.owner.isStaticOwner) // non-top level class reference that is phase inconsistent
209
+ if ! adaptOnly then
210
+ levelError(sym, tp, pos, " " )
211
+ else None
212
+ else if (! sym.owner.isStaticOwner && ! adaptOnly) // non-top level class reference that is phase inconsistent
209
213
levelError(sym, tp, pos, " " )
210
214
else
211
215
None
@@ -234,25 +238,26 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
234
238
* @return Some(msg) if unsuccessful where `msg` is a potentially empty error message
235
239
* to be added to the "inconsistent phase" message.
236
240
*/
237
- protected def tryHeal (sym : Symbol , tp : TypeRef , pos : SourcePosition )(implicit ctx : Context ): Option [Tree ] = {
241
+ protected def tryHeal (sym : Symbol , tp : TypeRef , pos : SourcePosition , adaptOnly : Boolean )(implicit ctx : Context ): Option [Tree ] = {
238
242
val reqType = defn.QuotedTypeClass .typeRef.appliedTo(tp)
239
243
val tag = ctx.typer.inferImplicitArg(reqType, pos.span)
240
244
241
245
tag.tpe match
242
246
case tp : TermRef =>
243
247
checkStable(tp, pos)
244
248
Some (ref(getQuoteTypeTags.getTagRef(tp)))
245
- case _ : SearchFailureType =>
249
+ case _ : SearchFailureType if ! adaptOnly =>
246
250
levelError(sym, tp, pos,
247
251
i """
248
252
|
249
253
| The access would be accepted with the right type tag, but
250
254
| ${ctx.typer.missingArgMsg(tag, reqType, " " )}""" )
251
- case _ =>
255
+ case _ if ! adaptOnly =>
252
256
levelError(sym, tp, pos,
253
257
i """
254
258
|
255
259
| The access would be accepted with a given $reqType""" )
260
+ case _ => None
256
261
}
257
262
258
263
private def levelError (sym : Symbol , tp : Type , pos : SourcePosition , errMsg : String )(using Context ) = {
0 commit comments