From 9f1ff63c7fadcaaedbb5b57f00949d4aa5ff8934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Mon, 22 Jul 2024 11:22:49 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20#20897:=20Make=20`Nothing=20=E2=8B=94=20N?= =?UTF-8?q?othing`=20and=20`Null=20=E2=8B=94=20Null`,=20as=20per=20spec.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `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.) --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 6 ++++-- compiler/test/dotc/pos-test-pickling.blacklist | 2 +- tests/pos/i20897.scala | 10 ++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 tests/pos/i20897.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index c8e00686e62b..1f3806fa0cc4 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -3187,9 +3187,11 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling else child }.filter(child => child.exists && child != cls) - // TODO? Special-case for Nothing and Null? We probably need Nothing/Null disjoint from Nothing/Null def eitherDerivesFromOther(cls1: Symbol, cls2: Symbol): Boolean = - cls1.derivesFrom(cls2) || cls2.derivesFrom(cls1) + if cls1 eq cls2 then + cls1 != defn.NothingClass && cls1 != defn.NullClass + else + cls1.derivesFrom(cls2) || cls2.derivesFrom(cls1) def smallestNonTraitBase(cls: Symbol): Symbol = cls.asClass.baseClasses.find(!_.is(Trait)).get diff --git a/compiler/test/dotc/pos-test-pickling.blacklist b/compiler/test/dotc/pos-test-pickling.blacklist index d6f962176ecc..b68ac7fc3b6e 100644 --- a/compiler/test/dotc/pos-test-pickling.blacklist +++ b/compiler/test/dotc/pos-test-pickling.blacklist @@ -67,6 +67,7 @@ mt-redux-norm.perspective.scala i18211.scala 10867.scala named-tuples1.scala +i20897.scala # Opaque type i5720.scala @@ -134,4 +135,3 @@ parsercombinators-new-syntax.scala hylolib-deferred-given hylolib-cb hylolib - diff --git a/tests/pos/i20897.scala b/tests/pos/i20897.scala new file mode 100644 index 000000000000..ecfac5b1615e --- /dev/null +++ b/tests/pos/i20897.scala @@ -0,0 +1,10 @@ +object Test: + type Disj[A, B] = + A match + case B => true + case _ => false + + def f(a: Disj[1 | Nothing, 2 | Nothing]): Unit = () + + val t = f(false) +end Test