Skip to content

Commit e65305d

Browse files
committed
Fix treatment of bottom types in OrType#join and baseType computations
1 parent f01c14d commit e65305d

File tree

3 files changed

+23
-8
lines changed

3 files changed

+23
-8
lines changed

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2098,25 +2098,27 @@ object SymDenotations {
20982098
computeTypeProxy
20992099

21002100
case tp: AndOrType =>
2101-
def computeAndOrType = {
2101+
def computeAndOrType: Type =
21022102
val tp1 = tp.tp1
21032103
val tp2 = tp.tp2
2104+
if !tp.isAnd then
2105+
if tp1.isBottomType && (tp1 frozen_<:< tp2) then return recur(tp2)
2106+
if tp2.isBottomType && (tp2 frozen_<:< tp1) then return recur(tp1)
21042107
val baseTp =
2105-
if (symbol.isStatic && tp.derivesFrom(symbol) && symbol.typeParams.isEmpty)
2108+
if symbol.isStatic && tp.derivesFrom(symbol) && symbol.typeParams.isEmpty then
21062109
symbol.typeRef
2107-
else {
2110+
else
21082111
val baseTp1 = recur(tp1)
21092112
val baseTp2 = recur(tp2)
21102113
val combined = if (tp.isAnd) baseTp1 & baseTp2 else baseTp1 | baseTp2
2111-
combined match {
2114+
combined match
21122115
case combined: AndOrType
21132116
if (combined.tp1 eq tp1) && (combined.tp2 eq tp2) && (combined.isAnd == tp.isAnd) => tp
21142117
case _ => combined
2115-
}
2116-
}
2118+
21172119
if (baseTp.exists && inCache(tp1) && inCache(tp2)) record(tp, baseTp)
21182120
baseTp
2119-
}
2121+
21202122
computeAndOrType
21212123

21222124
case JavaArrayType(_) if symbol == defn.ObjectClass =>

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3148,7 +3148,10 @@ object Types {
31483148
/** Replace or type by the closest non-or type above it */
31493149
def join(using Context): Type = {
31503150
if (myJoinPeriod != ctx.period) {
3151-
myJoin = TypeOps.orDominator(this)
3151+
myJoin =
3152+
if tp1 frozen_<:< tp2 then tp2
3153+
else if tp2 frozen_<:< tp1 then tp1
3154+
else TypeOps.orDominator(this)
31523155
core.println(i"join of $this == $myJoin")
31533156
assert(myJoin != this)
31543157
myJoinPeriod = ctx.period

tests/pos/i11968.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class C {
2+
def get(): Int = 0
3+
}
4+
5+
def g = {
6+
val s: String | Null = ???
7+
val l = s.length // ok
8+
val c: C | Null = ???
9+
c.get() // error: value get is not a member of C | Null
10+
}

0 commit comments

Comments
 (0)