Skip to content

Commit 13ac94e

Browse files
committed
Improve handling of disjunctions when comparing types
There were two problems in a comparison A | B <: C 1. If the LHS was `a.type | Nothing`, atoms computation did not correctly account for Nothing. 2. For other comparisons, the preliminary widen test was not done under a frozen constraint, and therefore cut off solutions. This caused a problem for the `summon[(1 | Nothing) <:< 1]` comparison even once (1) was fixed.
1 parent 5672999 commit 13ac94e

File tree

4 files changed

+26
-3
lines changed

4 files changed

+26
-3
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
441441
def widenOK =
442442
(tp2.widenSingletons eq tp2)
443443
&& (tp1.widenSingletons ne tp1)
444-
&& recurInFrozenGadt(tp1.widenSingletons, tp2)
444+
&& inFrozenConstraint(recurInFrozenGadt(tp1.widenSingletons, tp2))
445445

446446
def joinOK = tp2.dealiasKeepRefiningAnnots match {
447447
case tp2: AppliedType if !tp2.tycon.typeSymbol.isClass =>

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3104,7 +3104,10 @@ object Types {
31043104

31053105
private def ensureAtomsComputed()(using Context): Unit =
31063106
if atomsRunId != ctx.runId then
3107-
myAtoms = tp1.atoms | tp2.atoms
3107+
myAtoms =
3108+
if tp1.hasClassSymbol(defn.NothingClass) then tp2.atoms
3109+
else if tp2.hasClassSymbol(defn.NothingClass) then tp1.atoms
3110+
else tp1.atoms | tp2.atoms
31083111
val tp1w = tp1.widenSingletons
31093112
val tp2w = tp2.widenSingletons
31103113
myWidened = if ((tp1 eq tp1w) && (tp2 eq tp2w)) this else tp1w | tp2w

tests/neg/singletonOrs.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ object Get2As1 {
2424
def get2as11X:V = tuToV()(2) // error
2525
}
2626
class Or11Nothing extends Or11X[Nothing]
27-
def get2as1:1 = new Or11Nothing().get2as11X // error
27+
def get2as1:1 = new Or11Nothing().get2as11X // ok
2828

2929
def main(a:Array[String]) = {
3030
println(get2as1) // prints 2

tests/pos/i11003.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
object Foo
2+
3+
val x: Foo.type = Foo
4+
val y: Foo.type | Nothing = x
5+
val z: Foo.type = y
6+
val a: 1 | Nothing = 1
7+
val b: 1 = a
8+
9+
val intSuper = summon[(Int | Nothing) <:< Int]
10+
val intSub = summon[Int <:< (Int | Nothing)]
11+
val intEq = summon[Int =:= (Int | Nothing)]
12+
13+
val fooSuper = summon[(Foo.type | Nothing) <:< Foo.type]
14+
val fooSub = summon[Foo.type <:< (Foo.type | Nothing)]
15+
val fooEq = summon[Foo.type =:= (Foo.type | Nothing)]
16+
17+
val oneSuper = summon[(1 | Nothing) <:< 1]
18+
val oneSub = summon[1 <:< (1 | Nothing)]
19+
val oneEq = summon[1 =:= (1 | Nothing)]
20+

0 commit comments

Comments
 (0)