@@ -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
@@ -2762,20 +2763,23 @@ class Typer extends Namer
2762
2763
* If all this fails, error
2763
2764
* Parameters as for `typedUnadapted`.
2764
2765
*/
2765
- def adapt (tree : Tree , pt : Type , locked : TypeVars )(using Context ): Tree =
2766
- trace(i " adapting $tree to $pt" , typr, show = true ) {
2766
+ def adapt (tree : Tree , pt : Type , locked : TypeVars , tryGadtHealing : Boolean = true )(using Context ): Tree = {
2767
+ val last = Thread .currentThread.getStackTrace()(2 ).toString;
2768
+ trace/* .force*/ (i " adapting (tryGadtHealing= $tryGadtHealing) $tree to $pt\n {callsite: $last} " , typr, show = true ) {
2767
2769
record(" adapt" )
2768
- adapt1(tree, pt, locked)
2770
+ adapt1(tree, pt, locked, tryGadtHealing )
2769
2771
}
2772
+ }
2770
2773
2771
2774
final def adapt (tree : Tree , pt : Type )(using Context ): Tree =
2772
2775
adapt(tree, pt, ctx.typerState.ownedVars)
2773
2776
2774
- private def adapt1 (tree : Tree , pt : Type , locked : TypeVars )(using Context ): Tree = {
2777
+ private def adapt1 (tree : Tree , pt : Type , locked : TypeVars , tryGadtHealing : Boolean )(using Context ): Tree = {
2778
+ // assert(pt.exists && !pt.isInstanceOf[ExprType])
2775
2779
assert(pt.exists && ! pt.isInstanceOf [ExprType ] || ctx.reporter.errorsReported)
2776
2780
def methodStr = err.refStr(methPart(tree).tpe)
2777
2781
2778
- def readapt (tree : Tree )(using Context ) = adapt(tree, pt, locked)
2782
+ def readapt (tree : Tree , shouldTryGadtHealing : Boolean = tryGadtHealing )(using Context ) = adapt(tree, pt, locked, shouldTryGadtHealing )
2779
2783
def readaptSimplified (tree : Tree )(using Context ) = readapt(simplify(tree, pt, locked))
2780
2784
2781
2785
def missingArgs (mt : MethodType ) = {
@@ -3221,16 +3225,19 @@ class Typer extends Namer
3221
3225
}
3222
3226
3223
3227
def adaptToSubType (wtp : Type ): Tree = {
3228
+ debug.println(" adaptToSubType" )
3229
+ debug.println(" // try converting a constant to the target type" )
3224
3230
// try converting a constant to the target type
3225
3231
val folded = ConstFold (tree, pt)
3226
3232
if (folded ne tree)
3227
3233
return adaptConstant(folded, folded.tpe.asInstanceOf [ConstantType ])
3228
3234
3229
- // Try to capture wildcards in type
3235
+ debug.println( " // Try to capture wildcards in type" )
3230
3236
val captured = captureWildcards(wtp)
3231
3237
if (captured `ne` wtp)
3232
3238
return readapt(tree.cast(captured))
3233
3239
3240
+ debug.println(" // drop type if prototype is Unit" )
3234
3241
// drop type if prototype is Unit
3235
3242
if (pt isRef defn.UnitClass ) {
3236
3243
// local adaptation makes sure every adapted tree conforms to its pt
@@ -3240,6 +3247,7 @@ class Typer extends Namer
3240
3247
return tpd.Block (tree1 :: Nil , Literal (Constant (())))
3241
3248
}
3242
3249
3250
+ debug.println(" // convert function literal to SAM closure" )
3243
3251
// convert function literal to SAM closure
3244
3252
tree match {
3245
3253
case closure(Nil , id @ Ident (nme.ANON_FUN ), _)
@@ -3257,6 +3265,28 @@ class Typer extends Namer
3257
3265
case _ =>
3258
3266
}
3259
3267
3268
+ debug.println(" // try GADT approximation" )
3269
+ val foo = Inferencing .approximateGADT(wtp)
3270
+ debug.println(
3271
+ i """
3272
+ foo = $foo
3273
+ pt.isInstanceOf[SelectionProto] = ${pt.isInstanceOf [SelectionProto ]}
3274
+ ctx.gadt.nonEmpty = ${ctx.gadt.nonEmpty}
3275
+ pt.isMatchedBy = ${
3276
+ if (pt.isInstanceOf [SelectionProto ])
3277
+ pt.asInstanceOf [SelectionProto ].isMatchedBy(foo).toString
3278
+ else
3279
+ " <not a SelectionProto>"
3280
+ }
3281
+ """
3282
+ )
3283
+ pt match {
3284
+ case pt : SelectionProto if ctx.gadt.nonEmpty && pt.isMatchedBy(foo) =>
3285
+ return tpd.Typed (tree, TypeTree (foo))
3286
+ case _ => ;
3287
+ }
3288
+
3289
+ debug.println(" // try an extension method in scope" )
3260
3290
// try an extension method in scope
3261
3291
pt match {
3262
3292
case SelectionProto (name, mbrType, _, _) =>
@@ -3274,17 +3304,33 @@ class Typer extends Namer
3274
3304
val app = tryExtension(using nestedCtx)
3275
3305
if (! app.isEmpty && ! nestedCtx.reporter.hasErrors) {
3276
3306
nestedCtx.typerState.commit()
3307
+ debug.println(" returning ext meth in scope" )
3277
3308
return ExtMethodApply (app)
3278
3309
}
3279
3310
case _ =>
3280
3311
}
3281
3312
3313
+ debug.println(" // try an implicit conversion" )
3282
3314
// try an implicit conversion
3283
3315
val prevConstraint = ctx.typerState.constraint
3284
3316
def recover (failure : SearchFailureType ) =
3317
+ {
3318
+ debug.println(" recover" )
3285
3319
if (isFullyDefined(wtp, force = ForceDegree .all) &&
3286
3320
ctx.typerState.constraint.ne(prevConstraint)) readapt(tree)
3321
+ // else if ({
3322
+ // debug.println(i"tryGadtHealing=$tryGadtHealing && \n\tctx.gadt.nonEmpty=${ctx.gadt.nonEmpty}")
3323
+ // tryGadtHealing && ctx.gadt.nonEmpty
3324
+ // })
3325
+ // {
3326
+ // debug.println("here")
3327
+ // readapt(
3328
+ // tree = tpd.Typed(tree, TypeTree(Inferencing.approximateGADT(wtp))),
3329
+ // shouldTryGadtHealing = false,
3330
+ // )
3331
+ // }
3287
3332
else err.typeMismatch(tree, pt, failure)
3333
+ }
3288
3334
if ctx.mode.is(Mode .ImplicitsEnabled ) && tree.typeOpt.isValueType then
3289
3335
if pt.isRef(defn.AnyValClass ) || pt.isRef(defn.ObjectClass ) then
3290
3336
ctx.error(em " the result of an implicit conversion must be more specific than $pt" , tree.sourcePos)
0 commit comments