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