@@ -941,6 +941,9 @@ trait Infer extends Checkable {
941
941
|| isProperSubClassOrObject(sym1.safeOwner, sym2.owner)
942
942
)
943
943
944
+ // Note that this doesn't consider undetparams -- any type params in `ftpe1/2` need to be bound by their type (i.e. in a PolyType)
945
+ // since constructors of poly classes do not have their own polytype in their infos, this must be fixed up
946
+ // before calling this method (see memberTypeForSpecificity)
944
947
def isStrictlyMoreSpecific (ftpe1 : Type , ftpe2 : Type , sym1 : Symbol , sym2 : Symbol ): Boolean = {
945
948
// ftpe1 / ftpe2 are OverloadedTypes (possibly with one single alternative) if they
946
949
// denote the type of an "apply" member method (see "followApply")
@@ -1338,6 +1341,25 @@ trait Infer extends Checkable {
1338
1341
1339
1342
/* -- Overload Resolution ---------------------------------------------- */
1340
1343
1344
+ /** Adjust polymorphic class's constructor info to be polymorphic as well
1345
+ *
1346
+ * Normal polymorphic methods have a PolyType as their info, but a constructor reuses the type params of the class.
1347
+ * We wrap them in a PolyType here so that we get consistent behavior in determining specificity.
1348
+ *
1349
+ * @param pre
1350
+ * @param sym must not be overloaded!
1351
+ * @return `pre memberType sym`, unless `sym`` is a polymorphic class's constructor,
1352
+ * in which case a `PolyType` is wrapped around the ctor's info
1353
+ */
1354
+ private def memberTypeForSpecificity (pre : Type , sym : Symbol ) = {
1355
+ val tparsToAdd = if (sym.isConstructor) sym.owner.info.typeParams else Nil
1356
+
1357
+ if (tparsToAdd.isEmpty) pre memberType sym
1358
+ // Need to make sure tparsToAdd are owned by sym (the constructor), and not the class (`sym.owner`).
1359
+ // Otherwise, asSeenFrom will rewrite them to the corresponding symbols in `pre` (the new this type for `sym.owner`).
1360
+ else createFromClonedSymbolsAtOwner(tparsToAdd, sym, sym.info)(PolyType (_, _)).asSeenFrom(pre, sym.owner)
1361
+ }
1362
+
1341
1363
/** Assign `tree` the symbol and type of the alternative which
1342
1364
* matches prototype `pt`, if it exists.
1343
1365
* If several alternatives match `pt`, take parameterless one.
@@ -1350,8 +1372,8 @@ trait Infer extends Checkable {
1350
1372
val alts0 = alts filter (alt => isWeaklyCompatible(pre memberType alt, pt))
1351
1373
val alts1 = if (alts0.isEmpty) alts else alts0
1352
1374
val bests = bestAlternatives(alts1) { (sym1, sym2) =>
1353
- val tp1 = pre memberType sym1
1354
- val tp2 = pre memberType sym2
1375
+ val tp1 = memberTypeForSpecificity( pre, sym1)
1376
+ val tp2 = memberTypeForSpecificity( pre, sym2)
1355
1377
1356
1378
( (tp2 eq ErrorType )
1357
1379
|| isWeaklyCompatible(tp1, pt) && ! isWeaklyCompatible(tp2, pt)
@@ -1463,7 +1485,7 @@ trait Infer extends Checkable {
1463
1485
case tp => tp
1464
1486
}
1465
1487
1466
- private def followType (sym : Symbol ) = followApply(pre memberType sym)
1488
+ private def followType (sym : Symbol ) = followApply(memberTypeForSpecificity( pre, sym) )
1467
1489
// separate method to help the inliner
1468
1490
private def isAltApplicable (pt : Type )(alt : Symbol ) = context inSilentMode { isApplicable(undetparams, followType(alt), argtpes, pt) && ! context.reporter.hasErrors }
1469
1491
private def rankAlternatives (sym1 : Symbol , sym2 : Symbol ) = isStrictlyMoreSpecific(followType(sym1), followType(sym2), sym1, sym2)
0 commit comments