Skip to content

Commit 3ac0fb1

Browse files
committed
Move null comparison extractors into Nullables
1 parent 39da9ee commit 3ac0fb1

File tree

3 files changed

+39
-39
lines changed

3 files changed

+39
-39
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -656,42 +656,6 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
656656
acc(Nil, tree)
657657
}
658658

659-
/** An extractor for null comparisons */
660-
object CompareNull with
661-
662-
/** Matches one of
663-
*
664-
* tree == null, tree eq null, null == tree, null eq tree
665-
* tree != null, tree ne null, null != tree, null ne tree
666-
*
667-
* The second boolean result is true for equality tests, false for inequality tests
668-
*/
669-
def unapply(tree: Tree)(given Context): Option[(Tree, Boolean)] = tree match
670-
case Apply(Select(l, _), Literal(Constant(null)) :: Nil) =>
671-
testSym(tree.symbol, l)
672-
case Apply(Select(Literal(Constant(null)), _), r :: Nil) =>
673-
testSym(tree.symbol, r)
674-
case _ =>
675-
None
676-
677-
private def testSym(sym: Symbol, operand: Tree)(given Context) =
678-
if sym == defn.Any_== || sym == defn.Object_eq then Some((operand, true))
679-
else if sym == defn.Any_!= || sym == defn.Object_ne then Some((operand, false))
680-
else None
681-
682-
end CompareNull
683-
684-
/** An extractor for comparisons between a path and null. */
685-
object ComparePathNull with
686-
def unapply(tree: Tree)(given Context): Option[(TermRef, Boolean)] =
687-
CompareNull.unapply(tree) match
688-
case some @ Some((x, testEqual)) =>
689-
x.tpe match
690-
case ref: TermRef if ref.isStable => Some((ref, testEqual))
691-
case _ => None
692-
case none => None
693-
end ComparePathNull
694-
695659
/** Is this pattern node a catch-all or type-test pattern? */
696660
def isCatchCase(cdef: CaseDef)(implicit ctx: Context): Boolean = cdef match {
697661
case CaseDef(Typed(Ident(nme.WILDCARD), tpt), EmptyTree, _) =>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Constants._
1111
import Names._
1212
import StdNames._
1313
import Contexts._
14+
import Nullables.{CompareNull, TrackedRef}
1415

1516
object ConstFold {
1617

@@ -19,7 +20,7 @@ object ConstFold {
1920
/** If tree is a constant operation, replace with result. */
2021
def apply[T <: Tree](tree: T)(implicit ctx: Context): T = finish(tree) {
2122
tree match {
22-
case ComparePathNull(ref, testEqual) if ctx.notNullRefs.containsRef(ref) =>
23+
case CompareNull(TrackedRef(ref), testEqual) if ctx.notNullRefs.containsRef(ref) =>
2324
// TODO maybe drop once we have general Nullability?
2425
Constant(!testEqual)
2526
case Apply(Select(xt, op), yt :: Nil) =>

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

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package dotc
33
package typer
44

55
import core._
6-
import Types._, Contexts._, Symbols._, Decorators._
6+
import Types._, Contexts._, Symbols._, Decorators._, Constants._
77
import annotation.tailrec
88
import util.Property
99

@@ -30,6 +30,41 @@ object Nullables with
3030
*/
3131
private[typer] val AlwaysExcluded = Property.StickyKey[Nullables.Excluded]
3232

33+
/** An extractor for null comparisons */
34+
object CompareNull with
35+
36+
/** Matches one of
37+
*
38+
* tree == null, tree eq null, null == tree, null eq tree
39+
* tree != null, tree ne null, null != tree, null ne tree
40+
*
41+
* The second boolean result is true for equality tests, false for inequality tests
42+
*/
43+
def unapply(tree: Tree)(given Context): Option[(Tree, Boolean)] = tree match
44+
case Apply(Select(l, _), Literal(Constant(null)) :: Nil) =>
45+
testSym(tree.symbol, l)
46+
case Apply(Select(Literal(Constant(null)), _), r :: Nil) =>
47+
testSym(tree.symbol, r)
48+
case _ =>
49+
None
50+
51+
private def testSym(sym: Symbol, operand: Tree)(given Context) =
52+
if sym == defn.Any_== || sym == defn.Object_eq then Some((operand, true))
53+
else if sym == defn.Any_!= || sym == defn.Object_ne then Some((operand, false))
54+
else None
55+
56+
end CompareNull
57+
58+
/** An extractor for null-trackable references */
59+
object TrackedRef
60+
def unapply(tree: Tree)(given Context): Option[TermRef] = tree.typeOpt match
61+
case ref: TermRef if isTracked(ref) => Some(ref)
62+
case _ => None
63+
end TrackedRef
64+
65+
/** Is given reference tracked for nullability? */
66+
def isTracked(ref: TermRef)(given Context) = ref.isStable
67+
3368
given (excluded: List[Excluded])
3469
def containsRef(ref: TermRef): Boolean =
3570
excluded.exists(_.contains(ref))
@@ -95,7 +130,7 @@ object Nullables with
95130
def setExcluded(ifTrue: Excluded, ifFalse: Excluded) =
96131
tree.putAttachment(CondExcluded, EitherExcluded(ifTrue, ifFalse))
97132
if !curCtx.erasedTypes then tree match
98-
case ComparePathNull(ref, testEqual) =>
133+
case CompareNull(TrackedRef(ref), testEqual) =>
99134
if testEqual then setExcluded(Set(), Set(ref))
100135
else setExcluded(Set(ref), Set())
101136
case Apply(Select(x, _), y :: Nil) =>

0 commit comments

Comments
 (0)