@@ -3231,6 +3231,12 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
32313231 end provablyDisjointClasses
32323232
32333233 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+
32343240 // It is possible to conclude that two types applied are disjoint by
32353241 // looking at covariant type parameters if the said type parameters
32363242 // are disjoint and correspond to fields.
@@ -3239,9 +3245,20 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
32393245 def covariantDisjoint (tp1 : Type , tp2 : Type , tparam : TypeParamInfo ): Boolean =
32403246 provablyDisjoint(tp1, tp2, pending) && typeparamCorrespondsToField(cls.appliedRef, tparam)
32413247
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.
32433257 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+ }
32453262
32463263 args1.lazyZip(args2).lazyZip(cls.typeParams).exists {
32473264 (arg1, arg2, tparam) =>
0 commit comments