@@ -44,7 +44,6 @@ import transform.TypeUtils._
44
44
import reporting .trace
45
45
import Nullables .{NotNullInfo , given _ }
46
46
import NullOpsDecorator ._
47
- import config .Printers .debug
48
47
49
48
object Typer {
50
49
@@ -2773,8 +2772,7 @@ class Typer extends Namer
2773
2772
* Parameters as for `typedUnadapted`.
2774
2773
*/
2775
2774
def adapt (tree : Tree , pt : Type , locked : TypeVars , tryGadtHealing : Boolean = true )(using Context ): Tree = {
2776
- val last = Thread .currentThread.getStackTrace()(2 ).toString;
2777
- trace/* .force*/ (i " adapting (tryGadtHealing= $tryGadtHealing) $tree to $pt\n {callsite: $last} " , typr, show = true ) {
2775
+ trace(i " adapting $tree to $pt ${if (tryGadtHealing) " " else " (tryGadtHealing=false)" }\n " , typr, show = true ) {
2778
2776
record(" adapt" )
2779
2777
adapt1(tree, pt, locked, tryGadtHealing)
2780
2778
}
@@ -2784,7 +2782,6 @@ class Typer extends Namer
2784
2782
adapt(tree, pt, ctx.typerState.ownedVars)
2785
2783
2786
2784
private def adapt1 (tree : Tree , pt : Type , locked : TypeVars , tryGadtHealing : Boolean )(using Context ): Tree = {
2787
- // assert(pt.exists && !pt.isInstanceOf[ExprType])
2788
2785
assert(pt.exists && ! pt.isInstanceOf [ExprType ] || ctx.reporter.errorsReported)
2789
2786
def methodStr = err.refStr(methPart(tree).tpe)
2790
2787
@@ -3243,19 +3240,15 @@ class Typer extends Namer
3243
3240
}
3244
3241
3245
3242
def adaptToSubType (wtp : Type ): Tree = {
3246
- debug.println(" adaptToSubType" )
3247
- debug.println(" // try converting a constant to the target type" )
3248
3243
// try converting a constant to the target type
3249
3244
val folded = ConstFold (tree, pt)
3250
3245
if (folded ne tree)
3251
3246
return adaptConstant(folded, folded.tpe.asInstanceOf [ConstantType ])
3252
3247
3253
- debug.println(" // Try to capture wildcards in type" )
3254
3248
val captured = captureWildcards(wtp)
3255
3249
if (captured `ne` wtp)
3256
3250
return readapt(tree.cast(captured))
3257
3251
3258
- debug.println(" // drop type if prototype is Unit" )
3259
3252
// drop type if prototype is Unit
3260
3253
if (pt isRef defn.UnitClass ) {
3261
3254
// local adaptation makes sure every adapted tree conforms to its pt
@@ -3265,7 +3258,6 @@ class Typer extends Namer
3265
3258
return tpd.Block (tree1 :: Nil , Literal (Constant (())))
3266
3259
}
3267
3260
3268
- debug.println(" // convert function literal to SAM closure" )
3269
3261
// convert function literal to SAM closure
3270
3262
tree match {
3271
3263
case closure(Nil , id @ Ident (nme.ANON_FUN ), _)
@@ -3283,28 +3275,28 @@ class Typer extends Namer
3283
3275
case _ =>
3284
3276
}
3285
3277
3286
- debug.println(" // try GADT approximation" )
3287
- val foo = Inferencing .approximateGADT(wtp)
3288
- debug.println(
3289
- i """
3290
- foo = $foo
3278
+ val approximation = Inferencing .approximateGADT(wtp)
3279
+ gadts.println(
3280
+ i """ GADT approximation {
3281
+ approximation = $approximation
3291
3282
pt.isInstanceOf[SelectionProto] = ${pt.isInstanceOf [SelectionProto ]}
3292
3283
ctx.gadt.nonEmpty = ${ctx.gadt.nonEmpty}
3284
+ ctx.gadt = ${ctx.gadt.debugBoundsDescription}
3293
3285
pt.isMatchedBy = ${
3294
3286
if (pt.isInstanceOf [SelectionProto ])
3295
- pt.asInstanceOf [SelectionProto ].isMatchedBy(foo ).toString
3287
+ pt.asInstanceOf [SelectionProto ].isMatchedBy(approximation ).toString
3296
3288
else
3297
3289
" <not a SelectionProto>"
3298
3290
}
3291
+ }
3299
3292
"""
3300
3293
)
3301
3294
pt match {
3302
- case pt : SelectionProto if ctx.gadt.nonEmpty && pt.isMatchedBy(foo ) =>
3303
- return tpd.Typed (tree, TypeTree (foo ))
3295
+ case pt : SelectionProto if ctx.gadt.nonEmpty && pt.isMatchedBy(approximation ) =>
3296
+ return tpd.Typed (tree, TypeTree (approximation ))
3304
3297
case _ => ;
3305
3298
}
3306
3299
3307
- debug.println(" // try an extension method in scope" )
3308
3300
// try an extension method in scope
3309
3301
pt match {
3310
3302
case SelectionProto (name, mbrType, _, _) =>
@@ -3322,33 +3314,41 @@ class Typer extends Namer
3322
3314
val app = tryExtension(using nestedCtx)
3323
3315
if (! app.isEmpty && ! nestedCtx.reporter.hasErrors) {
3324
3316
nestedCtx.typerState.commit()
3325
- debug.println(" returning ext meth in scope" )
3326
3317
return ExtMethodApply (app)
3327
3318
}
3328
3319
case _ =>
3329
3320
}
3330
3321
3331
- debug.println(" // try an implicit conversion" )
3332
3322
// try an implicit conversion
3333
3323
val prevConstraint = ctx.typerState.constraint
3334
- def recover (failure : SearchFailureType ) =
3335
- {
3336
- debug.println(" recover" )
3324
+ def recover (failure : SearchFailureType ) = {
3325
+ def canTryGADTHealing : Boolean = {
3326
+ val isDummy = tree.hasAttachment(dummyTreeOfType.IsDummyTree )
3327
+ tryGadtHealing // allow GADT healing only once to avoid a loop
3328
+ && ctx.gadt.nonEmpty // GADT healing only makes sense if there are GADT constraints present
3329
+ && ! isDummy // avoid healing a dummy tree as it can lead to an error in a very specific case
3330
+ }
3331
+
3337
3332
if (isFullyDefined(wtp, force = ForceDegree .all) &&
3338
3333
ctx.typerState.constraint.ne(prevConstraint)) readapt(tree)
3339
- // else if ({
3340
- // debug.println(i"tryGadtHealing=$tryGadtHealing && \n\tctx.gadt.nonEmpty=${ctx.gadt.nonEmpty}")
3341
- // tryGadtHealing && ctx.gadt.nonEmpty
3342
- // })
3343
- // {
3344
- // debug.println("here")
3345
- // readapt(
3346
- // tree = tpd.Typed(tree, TypeTree(Inferencing.approximateGADT(wtp))),
3347
- // shouldTryGadtHealing = false,
3348
- // )
3349
- // }
3350
- else err.typeMismatch(tree, pt, failure)
3351
- }
3334
+ else if (canTryGADTHealing) {
3335
+ // try recovering with a GADT approximation
3336
+ val nestedCtx = ctx.fresh.setNewTyperState()
3337
+ val res =
3338
+ readapt(
3339
+ tree = tpd.Typed (tree, TypeTree (Inferencing .approximateGADT(wtp))),
3340
+ shouldTryGadtHealing = false ,
3341
+ )(using nestedCtx)
3342
+ if (! nestedCtx.reporter.hasErrors) {
3343
+ // GADT recovery successful
3344
+ nestedCtx.typerState.commit()
3345
+ res
3346
+ } else {
3347
+ // otherwise fail with the error that would have been reported without the GADT recovery
3348
+ err.typeMismatch(tree, pt, failure)
3349
+ }
3350
+ } else err.typeMismatch(tree, pt, failure)
3351
+ }
3352
3352
if ctx.mode.is(Mode .ImplicitsEnabled ) && tree.typeOpt.isValueType then
3353
3353
if pt.isRef(defn.AnyValClass ) || pt.isRef(defn.ObjectClass ) then
3354
3354
ctx.error(em " the result of an implicit conversion must be more specific than $pt" , tree.sourcePos)
0 commit comments