Skip to content

Commit 1bbd9d7

Browse files
committed
Modify stable path check for anytype
1 parent 1b5f622 commit 1bbd9d7

File tree

4 files changed

+34
-3
lines changed

4 files changed

+34
-3
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,24 @@ class CheckRealizable(using Context) {
116116
case _: SingletonType | NoPrefix =>
117117
Realizable
118118
case tp =>
119+
def checkAndType(x: TermRef, y: Type) =
120+
(realizability(x) eq Realizable) && (y <:< x.widen)
121+
val isStableAndType = tp match {
122+
case AndType(tr: TermRef, tp1) =>
123+
checkAndType(tr, tp1)
124+
case AndType(tp1, tr: TermRef) =>
125+
checkAndType(tr, tp1)
126+
case _ => false
127+
}
119128
def isConcrete(tp: Type): Boolean = tp.dealias match {
120129
case tp: TypeRef => tp.symbol.isClass
121130
case tp: TypeProxy => isConcrete(tp.underlying)
122131
case tp: AndType => isConcrete(tp.tp1) && isConcrete(tp.tp2)
123132
case tp: OrType => isConcrete(tp.tp1) && isConcrete(tp.tp2)
124133
case _ => false
125134
}
126-
if (!isConcrete(tp)) NotConcrete
135+
if isStableAndType then Realizable
136+
else if !isConcrete(tp) then NotConcrete
127137
else boundsRealizability(tp).andAlso(memberRealizability(tp))
128138
}
129139

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,9 @@ object Types {
170170
case tp: ExprType => tp.resultType.isStable
171171
case tp: AnnotatedType => tp.parent.isStable
172172
case tp: AndType =>
173-
tp.tp1.isStable && (realizability(tp.tp2) eq Realizable) ||
174-
tp.tp2.isStable && (realizability(tp.tp1) eq Realizable)
173+
def checkAndStable(x: Type, y: Type) =
174+
x.isStable && ((realizability(y) eq Realizable) || y <:< x.widen)
175+
checkAndStable(tp.tp1, tp.tp2) || checkAndStable(tp.tp2, tp.tp1)
175176
case _ => false
176177
}
177178

tests/explicit-nulls/neg/nn.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// `.nn` extension method only strips away the outer Null.
2+
3+
class Test {
4+
val s1: String | Null = ???
5+
val s2: String = s1.nn
6+
7+
val ss1: Array[String | Null] | Null = ???
8+
val ss2: Array[String | Null] = ss1.nn
9+
val ss3: Array[String] = ss1.nn // error
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class S {
2+
def i[T](x: T): x.type = x
3+
4+
def f[T <: AnyRef](x: T | Null): x.type & T = {
5+
if x != null then
6+
i[x.type](x)
7+
else
8+
throw Exception()
9+
}
10+
}

0 commit comments

Comments
 (0)