@@ -44,6 +44,7 @@ import transform.TypeUtils._
44
44
import reporting .trace
45
45
import Nullables .{NotNullInfo , given _ }
46
46
import NullOpsDecorator ._
47
+ import config .Printers .debug
47
48
48
49
object Typer {
49
50
@@ -2771,20 +2772,23 @@ class Typer extends Namer
2771
2772
* If all this fails, error
2772
2773
* Parameters as for `typedUnadapted`.
2773
2774
*/
2774
- def adapt (tree : Tree , pt : Type , locked : TypeVars )(using Context ): Tree =
2775
- trace(i " adapting $tree to $pt" , typr, show = true ) {
2775
+ 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 ) {
2776
2778
record(" adapt" )
2777
- adapt1(tree, pt, locked)
2779
+ adapt1(tree, pt, locked, tryGadtHealing )
2778
2780
}
2781
+ }
2779
2782
2780
2783
final def adapt (tree : Tree , pt : Type )(using Context ): Tree =
2781
2784
adapt(tree, pt, ctx.typerState.ownedVars)
2782
2785
2783
- private def adapt1 (tree : Tree , pt : Type , locked : TypeVars )(using Context ): Tree = {
2786
+ private def adapt1 (tree : Tree , pt : Type , locked : TypeVars , tryGadtHealing : Boolean )(using Context ): Tree = {
2787
+ // assert(pt.exists && !pt.isInstanceOf[ExprType])
2784
2788
assert(pt.exists && ! pt.isInstanceOf [ExprType ] || ctx.reporter.errorsReported)
2785
2789
def methodStr = err.refStr(methPart(tree).tpe)
2786
2790
2787
- def readapt (tree : Tree )(using Context ) = adapt(tree, pt, locked)
2791
+ def readapt (tree : Tree , shouldTryGadtHealing : Boolean = tryGadtHealing )(using Context ) = adapt(tree, pt, locked, shouldTryGadtHealing )
2788
2792
def readaptSimplified (tree : Tree )(using Context ) = readapt(simplify(tree, pt, locked))
2789
2793
2790
2794
def missingArgs (mt : MethodType ) = {
@@ -3239,16 +3243,19 @@ class Typer extends Namer
3239
3243
}
3240
3244
3241
3245
def adaptToSubType (wtp : Type ): Tree = {
3246
+ debug.println(" adaptToSubType" )
3247
+ debug.println(" // try converting a constant to the target type" )
3242
3248
// try converting a constant to the target type
3243
3249
val folded = ConstFold (tree, pt)
3244
3250
if (folded ne tree)
3245
3251
return adaptConstant(folded, folded.tpe.asInstanceOf [ConstantType ])
3246
3252
3247
- // Try to capture wildcards in type
3253
+ debug.println( " // Try to capture wildcards in type" )
3248
3254
val captured = captureWildcards(wtp)
3249
3255
if (captured `ne` wtp)
3250
3256
return readapt(tree.cast(captured))
3251
3257
3258
+ debug.println(" // drop type if prototype is Unit" )
3252
3259
// drop type if prototype is Unit
3253
3260
if (pt isRef defn.UnitClass ) {
3254
3261
// local adaptation makes sure every adapted tree conforms to its pt
@@ -3258,6 +3265,7 @@ class Typer extends Namer
3258
3265
return tpd.Block (tree1 :: Nil , Literal (Constant (())))
3259
3266
}
3260
3267
3268
+ debug.println(" // convert function literal to SAM closure" )
3261
3269
// convert function literal to SAM closure
3262
3270
tree match {
3263
3271
case closure(Nil , id @ Ident (nme.ANON_FUN ), _)
@@ -3275,6 +3283,28 @@ class Typer extends Namer
3275
3283
case _ =>
3276
3284
}
3277
3285
3286
+ debug.println(" // try GADT approximation" )
3287
+ val foo = Inferencing .approximateGADT(wtp)
3288
+ debug.println(
3289
+ i """
3290
+ foo = $foo
3291
+ pt.isInstanceOf[SelectionProto] = ${pt.isInstanceOf [SelectionProto ]}
3292
+ ctx.gadt.nonEmpty = ${ctx.gadt.nonEmpty}
3293
+ pt.isMatchedBy = ${
3294
+ if (pt.isInstanceOf [SelectionProto ])
3295
+ pt.asInstanceOf [SelectionProto ].isMatchedBy(foo).toString
3296
+ else
3297
+ " <not a SelectionProto>"
3298
+ }
3299
+ """
3300
+ )
3301
+ pt match {
3302
+ case pt : SelectionProto if ctx.gadt.nonEmpty && pt.isMatchedBy(foo) =>
3303
+ return tpd.Typed (tree, TypeTree (foo))
3304
+ case _ => ;
3305
+ }
3306
+
3307
+ debug.println(" // try an extension method in scope" )
3278
3308
// try an extension method in scope
3279
3309
pt match {
3280
3310
case SelectionProto (name, mbrType, _, _) =>
@@ -3292,17 +3322,33 @@ class Typer extends Namer
3292
3322
val app = tryExtension(using nestedCtx)
3293
3323
if (! app.isEmpty && ! nestedCtx.reporter.hasErrors) {
3294
3324
nestedCtx.typerState.commit()
3325
+ debug.println(" returning ext meth in scope" )
3295
3326
return ExtMethodApply (app)
3296
3327
}
3297
3328
case _ =>
3298
3329
}
3299
3330
3331
+ debug.println(" // try an implicit conversion" )
3300
3332
// try an implicit conversion
3301
3333
val prevConstraint = ctx.typerState.constraint
3302
3334
def recover (failure : SearchFailureType ) =
3335
+ {
3336
+ debug.println(" recover" )
3303
3337
if (isFullyDefined(wtp, force = ForceDegree .all) &&
3304
3338
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
+ // }
3305
3350
else err.typeMismatch(tree, pt, failure)
3351
+ }
3306
3352
if ctx.mode.is(Mode .ImplicitsEnabled ) && tree.typeOpt.isValueType then
3307
3353
if pt.isRef(defn.AnyValClass ) || pt.isRef(defn.ObjectClass ) then
3308
3354
ctx.error(em " the result of an implicit conversion must be more specific than $pt" , tree.sourcePos)
0 commit comments