Skip to content

Commit a399811

Browse files
committed
Handle invalid cast in code
The path-insensitive nature of the analysis will necessarily lead to invalid casts. We cannot report warnings for such invalid casts as that would lead to too many false positives. Instead, we suppress the warnings on invalid member selections resulted from invalid casts.
1 parent 62ddace commit a399811

File tree

3 files changed

+54
-7
lines changed

3 files changed

+54
-7
lines changed

compiler/src/dotty/tools/dotc/transform/init/Objects.scala

+13-7
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ object Objects:
133133

134134
def hasOuter(cls: ClassSymbol): Boolean = outers.contains(cls)
135135

136+
/**
137+
* Whether the given symbol is a member of the underlying object?
138+
*/
139+
def hasMember(sym: Symbol)(using Context): Boolean =
140+
klass.isSubClass(sym.owner)
141+
136142
def initVal(field: Symbol, value: Value)(using Context) = log("Initialize " + field.show + " = " + value + " for " + this, printer) {
137143
assert(!field.is(Flags.Mutable), "Field is mutable: " + field.show)
138144
assert(!vals.contains(field), "Field already set: " + field.show)
@@ -171,7 +177,7 @@ object Objects:
171177

172178
def show(using Context) =
173179
val valFields = vals.map(_.show + " -> " + _.show)
174-
"OfClass(" + klass.show + ", outer = " + outer + ", args = " + args.map(_.show) + ", vals = " + valFields + ")"
180+
"OfClass(" + klass.show + ", outer = " + outer + ", args = " + args.map(_.show) + ", vals = " + valFields + ", vars = " + vars + ")"
175181

176182
object OfClass:
177183
def apply(
@@ -612,7 +618,7 @@ object Objects:
612618
* @param needResolve Whether the target of the call needs resolution?
613619
*/
614620
def call(value: Value, meth: Symbol, args: List[ArgInfo], receiver: Type, superType: Type, needResolve: Boolean = true): Contextual[Value] = log("call " + meth.show + ", this = " + value.show + ", args = " + args.map(_.value.show), printer, (_: Value).show) {
615-
value match
621+
value.match
616622
case Cold =>
617623
report.warning("Using cold alias. " + Trace.show, Trace.position)
618624
Bottom
@@ -786,19 +792,19 @@ object Objects:
786792
else
787793
errorReadOtherStaticObject(State.currentObject, addr.owner)
788794
Bottom
789-
else if ref.isObjectRef && ref.klass.hasSource then
795+
else if ref.hasMember(target) && !target.isOneOf(Flags.JavaDefined, Flags.Scala2x) then
790796
report.warning("Access uninitialized field " + field.show + ". " + Trace.show, Trace.position)
791797
Bottom
792798
else
793-
// initialization error, reported by the initialization checker
799+
// Silent for invalid member selection from pattern matching, type cast
794800
Bottom
795801
else if ref.hasVal(target) then
796802
ref.valValue(target)
797-
else if ref.isObjectRef && ref.klass.hasSource then
803+
else if ref.hasMember(target) && !target.isOneOf(Flags.JavaDefined, Flags.Scala2x) then
798804
report.warning("Access uninitialized field " + field.show + ". " + Trace.show, Trace.position)
799805
Bottom
800806
else
801-
// initialization error, reported by the initialization checker
807+
// Silent for invalid member selection from pattern matching, type cast
802808
Bottom
803809

804810
else
@@ -856,7 +862,7 @@ object Objects:
856862
errorMutateOtherStaticObject(State.currentObject, addr.owner)
857863
else
858864
Heap.writeJoin(addr, rhs)
859-
else
865+
else if ref.hasMember(field) && !field.isOneOf(Flags.JavaDefined, Flags.Scala2x) then
860866
report.warning("Mutating a field before its initialization: " + field.show + ". " + Trace.show, Trace.position)
861867
end match
862868

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class A:
2+
var a = 10
3+
4+
def foo() = O.n // error
5+
6+
class B:
7+
var b = 20
8+
def bar() = O.n // error
9+
10+
object O:
11+
val o1: A | B = new A
12+
val o2: A | B = new B
13+
14+
if o1.isInstanceOf[A] then
15+
o1.asInstanceOf[A].foo()
16+
else
17+
o1.asInstanceOf[B].bar()
18+
19+
o2 match
20+
case o: A => o.foo()
21+
case o: B => o.bar()
22+
23+
val n = 10
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class A:
2+
var a = 10
3+
4+
class B:
5+
var b = 20
6+
7+
object O:
8+
val o: A | B = new A
9+
10+
if o.isInstanceOf[A] then
11+
o.asInstanceOf[A].a += 1
12+
else
13+
o.asInstanceOf[B].b += 2
14+
15+
o match
16+
case o: A => o.a += 1
17+
case o: B => o.b += 2
18+

0 commit comments

Comments
 (0)