Skip to content

Commit b813439

Browse files
committed
better return type for Var; inline without extra val assign; better notNullInfo after assign
1 parent 6a321ad commit b813439

File tree

4 files changed

+22
-12
lines changed

4 files changed

+22
-12
lines changed

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,6 @@ class Definitions {
321321
/** Methods in Object and Any that do not have a side effect */
322322
@tu lazy val pureMethods: List[TermSymbol] = List(Any_==, Any_!=, Any_equals, Any_hashCode,
323323
Any_toString, Any_##, Any_getClass, Any_isInstanceOf, Any_typeTest, Object_eq, Object_ne,
324-
// Even through Compiletime_notNull is not pure (contains asInstanceOf), as it is removed later,
325-
// we can consider it as pure.
326324
Compiletime_notNull.asInstanceOf[TermSymbol])
327325

328326
@tu lazy val AnyKindClass: ClassSymbol = {

compiler/src/dotty/tools/dotc/typer/Nullables.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ object Nullables with
9696
/** An extractor for null-trackable references */
9797
object TrackedRef
9898
def unapply(tree: Tree)(given Context): Option[TermRef] = tree.typeOpt match
99-
case ref: TermRef if isTracked(ref) => println("tr: " + ref); Some(ref)
99+
case ref: TermRef if isTracked(ref) => Some(ref)
100100
case _ => None
101101
end TrackedRef
102102

@@ -253,8 +253,11 @@ object Nullables with
253253

254254
given assignOps: (tree: Assign)
255255
def computeAssignNullable()(given Context): tree.type = tree.lhs match
256-
case TrackedRef(ref) =>
257-
tree.withNotNullInfo(NotNullInfo(Set(), Set(ref))) // TODO: refine with nullability type info
256+
case TrackedRef(ref) => tree.rhs.typeOpt match
257+
// If the type of rhs is `T|Null`, then the nullability of the lhs variable is no longer
258+
// trackable. We don't need to check whether the type `T` is correct here.
259+
case OrNull(_) => tree.withNotNullInfo(NotNullInfo(Set(), Set(ref)))
260+
case _ => tree
258261
case _ => tree
259262

260263
private val analyzedOps = Set(nme.EQ, nme.NE, nme.eq, nme.ne, nme.ZAND, nme.ZOR, nme.UNARY_!)

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,11 +349,17 @@ class Typer extends Namer
349349
}
350350

351351
def toNotNullTermRef(tree: Tree, pt: Type)(implicit ctx: Context): Tree = tree.tpe match
352-
case tp @ OrNull(tpnn) : TermRef
352+
case ref @ OrNull(tpnn) : TermRef
353353
if pt != AssignProto && // Ensure it is not the lhs of Assign
354-
ctx.notNullInfos.impliesNotNull(tp) =>
354+
ctx.notNullInfos.impliesNotNull(ref) =>
355+
// def $notNull[A, B](x: A | Null): B = x.asInstanceOf
356+
// For a TermRef x: T|Null,
357+
// if x is inmutable: $notNull[T, x.type & T](x),
358+
// if x is mutable: $notNull[T, T](x).
359+
val tpeA = TypeTree(tpnn)
360+
val tpeB = if (ref.symbol.is(Mutable)) tpeA else TypeTree(AndType(ref, tpnn))
355361
Apply(
356-
TypeApply(Ident(defn.Compiletime_notNull.namedType), TypeTree(tpnn) :: Nil),
362+
TypeApply(Ident(defn.Compiletime_notNull.namedType), tpeA :: tpeB :: Nil),
357363
tree :: Nil)
358364
case _ =>
359365
tree

library/src/scala/compiletime/package.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,14 @@ package object compiletime {
6868
*
6969
* ```
7070
* val x: String|Null = ???
71-
* val _:String = $notNull[String](x)
71+
* val _: String = $notNull[String, x.type & String](x)
72+
*
73+
* var y: String|Null = ???
74+
* val _: String = $notNull[String, String](x)
7275
* ```
7376
*
74-
* Since `$notNull` is erased later, if `x` is a stable path,
75-
* `$notNull(x)` is also a stable path.
77+
* Since `$notNull` is erased later, if `x.type` is a stable path,
78+
* the type of `$notNull(x)` is also a stable path.
7679
*/
77-
def $notNull[A](x: A | Null): x.type & A = x.asInstanceOf
80+
inline def $notNull[A, B](x: => A | Null): B = x.asInstanceOf
7881
}

0 commit comments

Comments
 (0)