@@ -3231,6 +3231,12 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
3231
3231
end provablyDisjointClasses
3232
3232
3233
3233
private def provablyDisjointTypeArgs (cls : ClassSymbol , args1 : List [Type ], args2 : List [Type ], pending : util.HashSet [(Type , Type )])(using Context ): Boolean =
3234
+ // sjrd: I will not be surprised when this causes further issues in the future.
3235
+ // This is a compromise to be able to fix #21295 without breaking the world.
3236
+ def cannotBeNothing (tp : Type ): Boolean = tp match
3237
+ case tp : TypeParamRef => cannotBeNothing(tp.paramInfo)
3238
+ case _ => ! (tp.loBound.stripTypeVar <:< defn.NothingType )
3239
+
3234
3240
// It is possible to conclude that two types applied are disjoint by
3235
3241
// looking at covariant type parameters if the said type parameters
3236
3242
// are disjoint and correspond to fields.
@@ -3239,9 +3245,20 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
3239
3245
def covariantDisjoint (tp1 : Type , tp2 : Type , tparam : TypeParamInfo ): Boolean =
3240
3246
provablyDisjoint(tp1, tp2, pending) && typeparamCorrespondsToField(cls.appliedRef, tparam)
3241
3247
3242
- // In the invariant case, direct type parameter disjointness is enough.
3248
+ // In the invariant case, we have more ways to prove disjointness:
3249
+ // - either the type param corresponds to a field, like in the covariant case, or
3250
+ // - one of the two actual args can never be `Nothing`.
3251
+ // The latter condition, as tested by `cannotBeNothing`, is ad hoc and was
3252
+ // not carefully evaluated to be sound. We have it because we had to
3253
+ // reintroduce the former condition to fix #21295, and alone, that broke a
3254
+ // lot of existing test cases.
3255
+ // Having either one of the two conditions be true is better than not requiring
3256
+ // any, which was the status quo before #21295.
3243
3257
def invariantDisjoint (tp1 : Type , tp2 : Type , tparam : TypeParamInfo ): Boolean =
3244
- provablyDisjoint(tp1, tp2, pending)
3258
+ provablyDisjoint(tp1, tp2, pending) && {
3259
+ typeparamCorrespondsToField(cls.appliedRef, tparam)
3260
+ || (cannotBeNothing(tp1) || cannotBeNothing(tp2))
3261
+ }
3245
3262
3246
3263
args1.lazyZip(args2).lazyZip(cls.typeParams).exists {
3247
3264
(arg1, arg2, tparam) =>
0 commit comments