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