The ID test offset for a prefixed identifier is now the offset of the
identifier after the `.`. This makes the analyzer and CFE behaviors
match much more closely, which eliminates a lot of nuisance
differences in the ID test expectations.
Change-Id: Icef1b2bf56b79bcf584d1eb153bdafd575e6cabb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195483
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Previously, if a type mismatch occurred on a named argument, e.g.:
int.fromEnvironment('foo', defaultValue: 'BAD')
the error would be reported on the entire NamedExpression
(`defaultValue: 'BAD'` in this example). Now, the error is just
reported on the expression (`'BAD'` in this example). This makes the
analyzer behavior more self-consistent (since now assignability errors
are now consistently reported at the site of the expression that can't
be assigned). It also makes the analyzer behavior more consistent
with the CFE.
This will make it possible, in a follow-up CL, to eliminate a lot of
the inconsistencies between analyzer and CFE in the "why not promoted"
ID tests.
Change-Id: I17db256959d730a22a5766f65d5c0736b627f244
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195489
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This makes the flow analysis tests more similar to the anaylzer and
CFE implementations, which look up the type of a `this.` property get
at the time it is analyzed, rather than storing it in the AST node.
Change-Id: Idee2a9c3ba0acbd2752db511c1aabfdff075b363
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194544
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Flow analysis unit tests now support implicit branch targets, and use
`LabeledStatement` directly in the case where the branch target is
explicit. This is more similar to how the language acutally behaves,
and paves the way for adding more sophisticated tests in the future.
Note that at the moment, there are no flow analysis tests where a
`continue` statement has a different target than the innermost loop,
so for now, the `continue_` function doesn't accept a target
parameter. I plan to add this functionality in the future, at the
time that I add tests that require it.
Change-Id: I2591ee3322ea4adba3e32dc76a29f0b3956058e5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194040
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This CL changes the responsibility for doing flow analysis of the
implicit variable write in a `for-in` loop as follows: if the `for-in`
loop does not declare a variable, but it assigns to a local variable,
then the flow analysis client is responsible for calling `write` on
entry to the loop.
This in turn allows us to use a single code path to track "why not
promoted" information related to all possible local variable writes;
we no longer need as much special case logic to handle for-in loops.
To make the analyzer integration slightly cleaner, we change the
argument type of FlowAnalysis.write to Node rather than Expression, so
that the analyzer can pass in the ForEachParts object when analyzing a
for-in loop.
Bug: https://github.com/dart-lang/sdk/issues/44898
Change-Id: I24b47be8eac2e276cd291a5b2f2e4444c911138f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193837
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This makes the flow analysis unit tests more similar to the behavior
of the analyzer and CFE, in that the types of various properties are a
property of the program being analyzed, not of the individual property
gets themselves.
Change-Id: I6ea164665093ee285325a64e80f3f52d7a63cf74
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193836
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
The ID tests for the "why not promoted" feature had some minor
unintentional errors in them. This CL fixes them:
- The constructor tests in
argument_type_not_assignable_nullability_error.dart tried to return
null from functions whose return type didn't allow it.
- The compoundAssignmentRhs test in
argument_type_not_assignable_nullability_error.dart tried to add an
`int` to an `int?`. The CFE considers this to be an error, but also
reports a follow-on error because it thinks the type of the
resulting expression is `num` (which is not assignable back to
`int`). To avoid the follow-on error, we use `num` for the type of
the variable to which compound assignment is being applied.
- The forElementInMap test in
for_in_loop_type_not_iterable_nullability_error.dart wasn't a proper
map (it contained two `null` elements, rather than a single map
entry `null: null`, which was what was intended).
There were also several tests for which we *don't* expect "why not
promoted" information; I added comments explaining why.
Change-Id: I91ddb88cb0f25f9b209df3eeb75d57d8270f877b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193561
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Rather than representing an assignment differently depending on what
kind of construct appears on its left hand side (as kernel does), we
represent all assignments as a single `_Write` type, and use an
`LValue` base class to represent the different kinds of constructs
that can appear on the left hand side. This representation will be
easier to expand into supporting more of the Dart language as we
expand the testing we want to be able to do in _fe_analyzer_shared.
Change-Id: I87b811176b2ba132fb992414c277cf2c6b81e03c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193180
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Add helper on DartType to compute the `NonNull` of a type and use this
instead of `withDeclaredNullability(Nullability.nonNullable).
Includes a fix in the computation of NonNull of FutureOr.
TEST=existing
Change-Id: I3399cbf89c7d3f3e90f1315b01f40957e798a1b1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193400
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
We now use a single AST node to represent try/catch/finally rather
than separate try/catch and try/finally nodes. This more closely
parallels the data structures used by the analyzer and CFE.
Change-Id: Ic4c1f1e4ac9e10ebf36afa4047c9c8b9ce151a1f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193093
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
The type of `this` is now stored in the test harness rather than in
the individual `this` AST objects. This more closely parallels how
`this` is handled in the analyzer and CFE.
Change-Id: I7c60aec8a14680beecca161ad25d681b82f79a2b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193092
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
The failure message now includes the stacktrace from when the
_CheckPromoted node was constructed; this makes it possible to quickly
find the line in the source code that encodes the expectation, which
is often much more useful than the stacktrace from the time the
failure was detected.
The stacktrace from the time the failure was detected still appears,
after the stacktrace from when the node was constructed.
Change-Id: If375e141a32b371e806399e42ff7cfaae9cf7873
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/192290
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This is necessary because `whyNotPromoted` needs to be called right
after visiting a subexpression, but it's not always possible to tell
that the type of that subexpression will result in an error until more
code has been visited.
Change-Id: If44e2bb55612c1ba7996b523c3ec078d7b80c865
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/191601
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Rather than represent types by strings in the flow analysis tests, we
have a "mini type" language that can represent function types, type
parameters, nullabilities, and promotions. This should make it easier
to build more sophisticated tests for shared code.
Change-Id: I66d15ad3dc6a871958ed01654600aea749fa0e65
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/190340
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Flow analysis stopped using this argument (the AST node for the
finally block) some time ago, but I kept it around so I could assert
that clients didn't unnecessarily store assigned variables info for
it. It's been long enough now that we can eliminate this code
entirely.
Change-Id: I8c64e2b4fc5b154f441ec2d057637f3dc9ced277
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/190060
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This CL plumbs the types of `this` and property get expression from
the CFE and analyzer into flow analysis, so that flow analysis will be
able to create more accurate "why not promoted" information for those
expression types. This made it possible to eliminate a clumsy aspect
of the previous implementation, namely that we would consider a
promotion attempt like `if (x.y == null) return;` as an attempt to
promote the type of `x.y` to `Object`; now we compute the type the
user is actually trying to promote to, so we will be able to generate
more accurate "why not promoted" messages.
Bug: https://github.com/dart-lang/sdk/issues/44898
Change-Id: I67f9fc59e72103194a1ea6b1c4dfeae8aeb194a2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/187064
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
The Node class hierarchy shouldn't be const constructible, because
flow analysis assumes it can distinguish nodes by identity, and we
don't want const canonicalization to prevent this.
Change-Id: I60f70a0ece77c8efbeaa001cbddb21d1dc8b4d6e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/187980
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This CL adds support for the following scenarios to the analyzer:
- Attempt to use a non-promoted nullable expression as the iterable of
a for-in loop
- Attempt to use a non-promoted nullable expression as the argument of
a `yield *` statement
- Attempt to implicitly invoke `.call` on a non-promoted nullable
expression
- Attempt to use a non-promoted nullable expression as the argument of
a spread operator (`...`) that is not null-aware
Some of these cases are already handled by the CFE. Others will be
addressed in a follow-up CL.
Change-Id: I3cf31b1496e1bd92fdd3f8192f04c98dff15077c
Bug: https://github.com/dart-lang/sdk/issues/44898
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/186320
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
When reporting that a null check is needed due to a lack of type
promotion, and the thing that was not promoted was a reference to a
field or property, the CFE and analyzer now report "why not promoted"
using a context message that points to the definition of the field or
getter. (Previously the CFE reported a context message with no
location, and the analyzer didn't report "why not promoted").
Bug: https://github.com/dart-lang/sdk/issues/44898
Change-Id: If1841727b8b60dd87c43f239e6a06b98f363801f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/184522
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This CL implements the core flow analysis infrastructure for tracking
reasons why an expression was not promoted. It supports the following
reasons:
- Expression was a property access
- Expression has been written to since it was promoted
I expect to add support for other non-promotion reasons in the future,
for example:
- `this` cannot be promoted
- Expression has been write captured
- Expression was a reference to a static field or top level variable
These non-promotion reasons are plumbed through to the CFE and
analyzer for the purpose of making errors easier for the user to
understand. For example, given the following code:
class C {
int? i;
f() {
if (i == null) return;
print(i.isEven);
}
}
The front end now prints:
../../tmp/test.dart:5:13: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
Try accessing using ?. instead.
print(i.isEven);
^^^^^^
Context: 'i' refers to a property so it could not be promoted.
Much work still needs to be done to round out this feature, for example:
- Currently the analyzer only shows the new "why not promoted"
messages when the "--verbose" flag is specified; this means the
feature is unlikely to be noticed by users.
- Currently the analyzer doesn't show a "why not promoted" message
when the non-promotion reason is that the expression is a property
access.
- We need one or more web pages explaining non-promotion reasons in
more detail so that the error messages can contain pointers to them.
- The analyzer and front end currently only show non-promotion reasons
for expressions of the form `x.y` where `x` fails to be promoted to
non-nullable. There are many other scenarios that should be
handled.
Change-Id: I0a12df74d0fc6274dfb3cb555abea81a75884231
Bug: https://github.com/dart-lang/sdk/issues/38773
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/181741
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
We now track the following additional information:
- All local variable reads and read captures (previously we only
tracked writes)
- For any conditional expression (`?:`) or if-test, the variables
written in the "then" branch
- For any logical and expression (`&&`), the variables written in the
right hand side of the expression
Tracking this information will allow us to implement legacy type
promotion as part of _fe_analyzer_shared, using the same API as flow
anaylsis, which will in turn allow a lot of front end and analyzer
code to be removed and simplified.
Change-Id: I01aaf64cefb989a4450c8e6d3a8373c1ca2b6dec
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/179980
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
The new implementation uses the same API as flow analysis. This
should allow us to significantly simplify the CFE and analyzer, by
dropping their implementations of legacy type promotion in favor of
the shared implementation.
This CL just introduces the new implementation and unit tests for it;
it does not integrate it with the analyzer or CFE. I will follow up
with a CL that does the integration.
Change-Id: Ie07b3b39604d6a022ad42f3ae6b648a317c8af28
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/179560
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
The only references that are promotable are references to variables,
however in the near future I'll be adding logic to flor analysis to
keep track of attempts to promote fields; this will require tracking
references to property gets as well as references to `this`, so we
need to start building up data structures to track those references.
Bug: https://github.com/dart-lang/sdk/issues/38773
Change-Id: I0e3fd44f580bb85db3e8f405675b66aa4069e455
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/179280
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
These test harness methods now take strings rather than Type objects,
which should make the tests easier to read (and less work to write).
Change-Id: I160bb7a7a61116e18736d414d5a549971d851c02
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/178883
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
When analyzing code like this with the
`allowLocalBooleanVarsToPromote` flag enabled, don't treat a variable
containing `null` as equivalent to a literal `null`. For example:
f(int? x) {
var y = null;
if (x != y) {
print(x + 1); // ERROR: x must be null checked.
}
}
The rationale is that flow analysis doesn't promote variables that are
known to be `null` to the `Null` type, so it seems like it would be
inconsistent if we used the fact that they're `null` to promote other
variables.
Bug: https://github.com/dart-lang/language/issues/1274
Change-Id: Icfa14104936a26732353921e3a29a840c53d4d52
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/176560
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This CL adds functionality to FlowAnalysis.variableRead so that if the
truth value of the variable is known to be correlated with other flow
analysis state, that state can be restored. This allows promotion
based on boolean variables in addition to boolean expressions, e.g.:
int? x = ...;
var xIsNotNull = x != null;
if (xIsNotNull) {
print(x + 1); // Ok; x is known to be non-null.
}
This functionality is not enabled yet; it is hidden behind the flag
`allowLocalBooleanVarsToPromoteByDefault`.
Bug: https://github.com/dart-lang/language/issues/1274
Change-Id: I2a0183b69d285193db7acb36cc6af5c34e165c2c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/176500
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>