Skip to content

Commit 9f1ff63

Browse files
committed
Fix scala#20897: Make Nothing ⋔ Nothing and Null ⋔ Null, as per spec.
`derivesFrom` normally returns `false` when the receiver is `Nothing` or `Null`. However, it returns `true` if the right-hand- side happens to be exactly the same class. For the purpose of computing `provablyDisjoint`, we have to explicitly exclude those. (Note that the spec text per se only explicitly specifies `Nothing ⋔ Nothing`, not `Null ⋔ Null`, but that's because the spec text punts on the `Null` issue. The intent of `provablyDisjoint` is that there is no *non-null* value belonging to both types.)
1 parent af933c4 commit 9f1ff63

File tree

3 files changed

+15
-3
lines changed

3 files changed

+15
-3
lines changed

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3187,9 +3187,11 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
31873187
else child
31883188
}.filter(child => child.exists && child != cls)
31893189

3190-
// TODO? Special-case for Nothing and Null? We probably need Nothing/Null disjoint from Nothing/Null
31913190
def eitherDerivesFromOther(cls1: Symbol, cls2: Symbol): Boolean =
3192-
cls1.derivesFrom(cls2) || cls2.derivesFrom(cls1)
3191+
if cls1 eq cls2 then
3192+
cls1 != defn.NothingClass && cls1 != defn.NullClass
3193+
else
3194+
cls1.derivesFrom(cls2) || cls2.derivesFrom(cls1)
31933195

31943196
def smallestNonTraitBase(cls: Symbol): Symbol =
31953197
cls.asClass.baseClasses.find(!_.is(Trait)).get

compiler/test/dotc/pos-test-pickling.blacklist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ mt-redux-norm.perspective.scala
6767
i18211.scala
6868
10867.scala
6969
named-tuples1.scala
70+
i20897.scala
7071

7172
# Opaque type
7273
i5720.scala
@@ -134,4 +135,3 @@ parsercombinators-new-syntax.scala
134135
hylolib-deferred-given
135136
hylolib-cb
136137
hylolib
137-

tests/pos/i20897.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
object Test:
2+
type Disj[A, B] =
3+
A match
4+
case B => true
5+
case _ => false
6+
7+
def f(a: Disj[1 | Nothing, 2 | Nothing]): Unit = ()
8+
9+
val t = f(false)
10+
end Test

0 commit comments

Comments
 (0)