@@ -1260,6 +1260,20 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
1260
1260
Nil
1261
1261
}
1262
1262
1263
+ /** Try to produce joint arguments for a glb `A[T_1, ..., T_n] & A[T_1', ..., T_n']` using
1264
+ * the following strategies:
1265
+ *
1266
+ * - if corresponding parameter variance is co/contra-variant, the glb/lub.
1267
+ * - if arguments are the same, that argument.
1268
+ * - if at least one of the arguments if a TypeBounds, the union of
1269
+ * the bounds.
1270
+ * - if homogenizeArgs is set, and arguments can be unified by instantiating
1271
+ * type parameters, the unified argument.
1272
+ * - otherwise NoType
1273
+ *
1274
+ * The unification rule is contentious because it cuts the constraint set.
1275
+ * Therefore it is subject to Config option `alignArgsInAnd`.
1276
+ */
1263
1277
def glbArgs (args1 : List [Type ], args2 : List [Type ], tparams : List [TypeParamInfo ]): List [Type ] =
1264
1278
tparams match {
1265
1279
case tparam :: tparamsRest =>
@@ -1273,6 +1287,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
1273
1287
else if (arg1.isInstanceOf [TypeBounds ] || arg2.isInstanceOf [TypeBounds ])
1274
1288
TypeBounds (lub(arg1.loBound, arg2.loBound),
1275
1289
glb(arg1.hiBound, arg2.hiBound))
1290
+ else if (homogenizeArgs && ! frozenConstraint && isSameType(arg1, arg2)) arg1
1276
1291
else NoType
1277
1292
glbArg :: glbArgs(args1Rest, args2Rest, tparamsRest)
1278
1293
case nil =>
@@ -1430,26 +1445,11 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
1430
1445
// opportunistically merge same-named refinements
1431
1446
// this does not change anything semantically (i.e. merging or not merging
1432
1447
// gives =:= types), but it keeps the type smaller.
1433
- // @!!! still needed?
1434
1448
case tp1 : RefinedType =>
1435
1449
tp2 match {
1436
1450
case tp2 : RefinedType if tp1.refinedName == tp2.refinedName =>
1437
- // Given two refinements `T1 { X = S1 }` and `T2 { X = S2 }` rewrite to
1438
- // `T1 & T2 { X B }` where `B` is the conjunction of the bounds of `X` in `T1` and `T2`.
1439
- //
1440
- // However, if `homogenizeArgs` is set, and both aliases `X = Si` are
1441
- // nonvariant, and `S1 =:= S2` (possibly by instantiating type parameters),
1442
- // rewrite instead to `T1 & T2 { X = S1 }`. This rule is contentious because
1443
- // it cuts the constraint set. On the other hand, without it we would replace
1444
- // the two aliases by `T { X >: S1 | S2 <: S1 & S2 }`, which looks weird
1445
- // and is probably not what's intended.
1446
- val rinfo1 = tp1.refinedInfo
1447
- val rinfo2 = tp2.refinedInfo
1448
- val parent = tp1.parent & tp2.parent
1449
- if (homogenizeArgs && rinfo1.isAlias && rinfo2.isAlias) // @!!! probably drop this case?
1450
- isSameType(rinfo1, rinfo2) // establish new constraint
1451
-
1452
- tp1.derivedRefinedType(parent, tp1.refinedName, rinfo1 & rinfo2)
1451
+ tp1.derivedRefinedType(tp1.parent & tp2.parent, tp1.refinedName,
1452
+ tp1.refinedInfo & tp2.refinedInfo)
1453
1453
case _ =>
1454
1454
NoType
1455
1455
}
0 commit comments