@@ -8,8 +8,15 @@ import Contexts.Context, Types._, Constants._, Decorators._, Symbols._
8
8
import TypeUtils ._ , TypeErasure ._
9
9
10
10
11
- /** Implements partial `isInstanceOf` evaluation according to the matrix on:
12
- * https://github.com/lampepfl/dotty/issues/1255
11
+ /** Implements partial evaluation of `sc.isInstanceOf[Sel]` according to:
12
+ *
13
+ * +-------------+----------------------------+----------------------------+------------------+
14
+ * | Sel\sc | trait | class | final class |
15
+ * +-------------+----------------------------+----------------------------+------------------+
16
+ * | trait | ? | ? | statically known |
17
+ * | class | ? | false if classes unrelated | statically known |
18
+ * | final class | false if classes unrelated | false if classes unrelated | statically known |
19
+ * +-------------+----------------------------+----------------------------+------------------+
13
20
*
14
21
* This is a generalized solution to raising an error on unreachable match
15
22
* cases and warnings on other statically known results of `isInstanceOf`.
@@ -36,26 +43,28 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
36
43
* the correct warnings, or an error if statically known to be false in
37
44
* match
38
45
*/
39
- def handleStaticallyKnown (tree : Select , scrutinee : Type , selector : Type , inMatch : Boolean , pos : Position ): Tree =
40
- if (! (scrutinee <:< selector) && inMatch) {
46
+ def handleStaticallyKnown (tree : Select , scrutinee : Type , selector : Type , inMatch : Boolean , pos : Position ): Tree = {
47
+ val scrutineeSubSelector = scrutinee <:< selector
48
+ if (! scrutineeSubSelector && inMatch) {
41
49
ctx.error(
42
50
s " this case is unreachable due to ` ${selector.show}` not being a subclass of ` ${scrutinee.show}` " ,
43
51
Position (pos.start - 5 , pos.end - 5 )
44
52
)
45
53
rewrite(tree, to = false )
46
- } else if (! (scrutinee <:< selector) && ! inMatch) {
54
+ } else if (! scrutineeSubSelector && ! inMatch) {
47
55
ctx.warning(
48
56
s " this will always yield false since ` ${scrutinee.show}` is not a subclass of ` ${selector.show}` (will be optimized away) " ,
49
57
pos
50
58
)
51
59
rewrite(tree, to = false )
52
- } else if (scrutinee <:< selector && ! inMatch) {
60
+ } else if (scrutineeSubSelector && ! inMatch) {
53
61
ctx.warning(
54
- s " this will always yield true since ` ${scrutinee.show}` is a subclass of ` ${selector.show}` (will be optimized away) " ,
62
+ s " this will always yield true if the scrutinee is non-null, since ` ${scrutinee.show}` is a subclass of ` ${selector.show}` (will be optimized away) " ,
55
63
pos
56
64
)
57
65
rewrite(tree, to = true )
58
- } else /* if (scrutinee <:< selector && inMatch) */ rewrite(tree, to = true )
66
+ } else /* if (scrutineeSubSelector && inMatch) */ rewrite(tree, to = true )
67
+ }
59
68
60
69
/** Rewrites cases with unrelated types */
61
70
def handleFalseUnrelated (tree : Select , scrutinee : Type , selector : Type , inMatch : Boolean ) =
@@ -74,12 +83,12 @@ class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
74
83
}
75
84
76
85
/** Rewrites the select to a boolean if `to` is false or if the qualifier
77
- * is a primitive .
86
+ * is a value class .
78
87
*
79
88
* If `to` is set to true and the qualifier is not a primitive, the
80
89
* instanceOf is replaced by a null check, since:
81
90
*
82
- * `srutinee .isInstanceOf[Selector]` if `scrutinee eq null`
91
+ * `scrutinee .isInstanceOf[Selector]` if `scrutinee eq null`
83
92
*/
84
93
def rewrite (tree : Select , to : Boolean ): Tree =
85
94
if (! to || ! tree.qualifier.tpe.widen.derivesFrom(defn.AnyRefAlias ))
0 commit comments