@@ -1296,23 +1296,50 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
1296
1296
// # skipped implicit parameters in tp1 - # skipped implicit parameters in tp2
1297
1297
var implicitBalance : Int = 0
1298
1298
1299
+ /** Widen the type of synthetic implied methods from the implementation class to the
1300
+ * type that's implemented. Example
1301
+ *
1302
+ * implied I[X] for T { ... }
1303
+ *
1304
+ * This desugars to
1305
+ *
1306
+ * class I[X] extends T { ... }
1307
+ * implied def I[X]: I[X] = new I[X]
1308
+ *
1309
+ * To compare specificity we should compare with `T`, not with its implementation `I[X]`.
1310
+ * No such widening is performed for implied aliases, which are not synthetic. E.g.
1311
+ *
1312
+ * implied J[X] for T = rhs
1313
+ *
1314
+ * already has the right result type `T`. Neither is widening performed for implied
1315
+ * objects, since these are anyway taken to be more specific than methods
1316
+ * (by condition 3a above).
1317
+ */
1318
+ def widenImplied (tp : Type , alt : TermRef ): Type =
1319
+ if (alt.symbol.is(SyntheticImpliedMethod ))
1320
+ tp.parents match {
1321
+ case Nil => tp
1322
+ case ps => ps.reduceLeft(AndType (_, _))
1323
+ }
1324
+ else tp
1325
+
1299
1326
/** Drop any implicit parameter section */
1300
- def stripImplicit (tp : Type , weight : Int ): Type = tp match {
1327
+ def stripImplicit (tp : Type , alt : TermRef , weight : Int ): Type = tp match {
1301
1328
case mt : MethodType if mt.isImplicitMethod =>
1302
1329
implicitBalance += mt.paramInfos.length * weight
1303
- resultTypeApprox(mt)
1330
+ widenImplied( resultTypeApprox(mt), alt )
1304
1331
case pt : PolyType =>
1305
- pt.derivedLambdaType(pt.paramNames, pt.paramInfos, stripImplicit(pt.resultType, weight))
1332
+ pt.derivedLambdaType(pt.paramNames, pt.paramInfos, stripImplicit(pt.resultType, alt, weight))
1306
1333
case _ =>
1307
- tp
1334
+ widenImplied(tp, alt)
1308
1335
}
1309
1336
1310
1337
val owner1 = if (alt1.symbol.exists) alt1.symbol.owner else NoSymbol
1311
1338
val owner2 = if (alt2.symbol.exists) alt2.symbol.owner else NoSymbol
1312
1339
val ownerScore = compareOwner(owner1, owner2)
1313
1340
1314
- val tp1 = stripImplicit(alt1.widen, - 1 )
1315
- val tp2 = stripImplicit(alt2.widen, + 1 )
1341
+ val tp1 = stripImplicit(alt1.widen, alt1, - 1 )
1342
+ val tp2 = stripImplicit(alt2.widen, alt2, + 1 )
1316
1343
def winsType1 = isAsSpecific(alt1, tp1, alt2, tp2)
1317
1344
def winsType2 = isAsSpecific(alt2, tp2, alt1, tp1)
1318
1345
0 commit comments