Description
Consider the following code (from dart-lang/co19#3126 (comment)):
class S {}
class T extends S {
void foo() {}
}
void main() {
var s = S();
s is T;
s = T();
s.foo(); // Error, so `T` was not a type of interest, but it should be.
}
According to the flow analysis spec:
true(s is T)
should add the typeT
to thetested
list in theVariableModel
fors
.- Since there is no specific rule defining
after(N)
foris
expressions, the general ruleafter(N) = join(true(N), false(N))
should be used (see the Expressions subsection). join
is based onjoinV
, and the definition ofjoinV
(see the Models subsection) says thatjoinV
takes the union of thetested
lists from the two branches.- So
after(s is T)
should includeT
as one of thetested
types fors
. (In other words,T
should be a type of interest fors
after thisis
check).
What's happening instead is that instead of using the general rule after(N) = join(true(N), false(N))
for is
expressions, flow analysis is failing to update its description of the _current
flow state, so in effect what the implementation is doing is this (I've highlighted the difference from the spec in bold):
- instance check: If
N
is an expression of the formE1 is S
where the static type ofE1
isT
then:
- Let
before(E1) = before(N)
- If
T
is a bottom type, then:
- Let
true(N) = unreachable(after(E1))
.- Let
false(N) = after(E1)
.- Otherwise:
- Let
true(N) = promote(E1, S, after(E1))
- Let
false(N) = promote(E1, factor(T, S), after(E1))
- Let
after(N) = after(E1)
In practice this is pretty benign because most of the time people perform is
tests, they do so in a conditional context, so the flow models that get propagated forward come from true(N)
and false(N)
(which are behaving correctly). The incorrect behavior only happens if the is
test isn't used in a condition, so the flow model that gets propagated forward come from the buggy after(N)
.
Since the bug only manifests if an is
test is used in an unusual way, and only causes problems with types of interest, I'm classifying this as a P3. I will still try to get to fixing it though.