During top-level inference we cannot emit errors. With this change
the inferrer controls whether to create and report an error or to create
a revisitable node.
Change-Id: Ia7821c6d2628fdae0897f3cd6108ef12d2f096df
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122782
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Previously, we made heavy use of operator== in the flow analysis
tests. But we also tried to verify that the flow analysis engine
didn't compare types with operator==. This was kludgy, because it
meant that we had to use a global variable to keep track of whether a
use of _Type.operator== should succeed. It was also kludgy because it
required an implementation of operator== in flow analysis code that
was solely meant for testing.
By using custom matchers, we can get the same level of testing
flexibility without making use of operator== anywhere.
Also, fixed a few flaws in the tests for "join". They were
accidentally setting up variables in the already-written state, so the
"assigned" subtest was passing in spite of incorrect expectations.
Change-Id: If326678aeb20a62433ad090968e150738ba5dc59
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/123140
Reviewed-by: Johnni Winther <johnniwinther@google.com>
If the RHS of an assignment is a subtype of the current promoted type
(or one of the previously promoted types), any relevant promotions are
kept.
So for example:
if (x is int) {
x = x + 1; // Still an int!
print(x.isEVen); // ok
}
This required two significant changes:
- Clients must now tell the flow analysis engine the type of the RHS
of the assignment. This required some refactoring in the analyzer,
because this information wasn't always easily available at the point
where we were calling flow analysis.
- The flow analysis engine now has to keep track of a "chain" of the
currently active promotions, so that it can potentially un-do some
promotions but not others. This meant that the algorithms for
"join" and "restrict" had to be reworked.
In a future CL I'll add the ability for assignments to promote to
types that have been previously checked against ("types of interest"),
e.g.:
if (x is! int) {
x = 0; // x is now an int!
}
// x is now known to be an int because it's promoted in both branches
Change-Id: I63d6c9a2021b045d391b2d9c674e9a2e5f770e62
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/123003
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This should make it easier to verify that the CFE implementation is
correct.
Note that this effort encountered a few bugs in the analyzer
implementation, which are marked with TODOs. I will fix them in
follow-up CLs.
Change-Id: Ic164a1cf214b5730f848b17db2838c29d25b00d0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122850
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Before this CL a part like "part ' package:foo/bar.dart';" would crash
the incremental compiler because the part specifies a scheme that is
invalid.
Change-Id: I567df0a68ff8709e4ca95d24e6dabc4d959c95fb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122862
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Previously, the client was responsible for querying AssignedVariables
to find the variables assigned and captured during constructs like
loops, and passing that information into FlowAnalysis methods. With
this CL, the client simply passes AssignedVariables into the
FlowAnalysis constructor, and the lookup happens automatically.
Change-Id: Ifbbf8ba8ea0d0f8a31d41244892c8c816eea56dd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122731
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
When analyzing an expression like `x += y`, where `x` may be type
promoted, we need to consider x's unpromoted type when determining
whether the result of the addition may be assigned to `x`. Before
flow analysis, we didn't need to worry about this subtlety because the
appearance of `x` on the LHS of an assignment used to disqualify it
from type promotion within any scopes containing the assignment.
Change-Id: I17887c457c9d0ce17ce704884e04d93ca8a3e925
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122587
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This was already working, it just needed some updates to the test
infrastructure so we could test it properly.
Change-Id: Ie838fb50cf90aabd19c6e0c637df546ddcda16d7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122584
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
When promoting a type parameter, we need to create an intersection
type (e.g. "T & int"). Such a type is represented in the analyzer and
the front end as a type parameter type pointing to the same type
variable, but with a different bound.
Change-Id: I1655f9242d913ca958c279cc80c3f6329f6b396d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122581
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Previously, in the flow analysis reachability tests, we only annotated
a node as unreachable if it wasn't "covered" by a parent node that was
already marked as unreachable. This made the tests more compact, but
it meant that the testing was less complete, because it meant that we
weren't verifying that the nodes inside of unreachable nodes were also
unreachable.
This CL changes the tests so that we mark every unreachable node as
unreachable, with one small exception: for an expression statement, we
don't mark the expression; we just mark the statement as unreachable,
and we have an assertion in the data extractor to verify that the
expression's reachability matches that of the statement.
Change-Id: I92454c72e9704b34e2dbafb9f5f19a8ee31f8f15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122583
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
The use of the helper removed the creation some unneeded temporary
variables in extension access which is reflected in the expectation
changes.
Change-Id: Ice6afcb223b7740c2555a076c3ddae9a9d4f092d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122394
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Previously, any attempt to promote type A to type B produced type B if
B was a subtype of A, and failed otherwise. But in order to support
promotion of type parameters, we need the ability to produce a fresh
"intersection type" (e.g. `T & int`). The new
`TypeOperations.tryPromoteToType method` makes this possible by giving
the client the opportunity to synthesize the new type when necessary.
Change-Id: If671d5d865f38469a878329180c3a1c94e25a42c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122582
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Previously, it was the caller's responsibility to determine if the
subexpression of an "is" expression was a read of a promotable
variable. Now, the caller calls isExpression_end regardless of what
the subexpression is, and flow analysis determines whether promotion
should happen or not.
Change-Id: Ibba689935580d4e9c5ab79e5afb534c173386232
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122411
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Binary operations and parenthesized expression are shorted which they
shouldn't be. Also, so complex expressions, like compound assignment,
are not handled because they need to be encoded in a more high-level
internal expression to support choosing the receiver based on shorting.
Change-Id: I0bdeabdc21da7d80f533ea0880662bfb11341c6e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121856
Reviewed-by: Aske Simon Christensen <askesc@google.com>