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>
Some tests in pkg/frontend/test are actually test suites written using the
pkg/testing framework.
This change runs these suites using a custom test runner instead of simply
running the test file, which makes the individual test results, timings and
logs available to the test system.
Change-Id: Iae5f37d9bd1b3e9b26c66443fe10e5cca6a6b6bf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118540
Commit-Queue: Karl Klose <karlklose@google.com>
Reviewed-by: Jonas Termansen <sortie@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Instead of forcing the client to provide a way to de-parenthesize an
expression, the client informs flow analysis when a parenthesized
expression is encountered. This reduces the runtime overhead to zero
for non-parenthesized expressions, and it saves the front end from
having to worry about support for parenthesized expressions (since its
internal representation doesn't care about parentheses).
Change-Id: I0bb6e91c87acaa05591e1b075da18700b11e4aae
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121080
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
With this, once can for instance run
out/ReleaseX64/dart pkg/front_end/test/parser_test.dart -DupdateExpectations=true -Dtrace=true -- parser_test/nnbd/nullCheckOnIndex
and from the output see where stuff was called, e.g.
beginFormalParameters((, MemberKind.TopLevelMethod) (package:front_end/src/fasta/parser/parser.dart:1227:14)
and
parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod) (package:front_end/src/fasta/parser/parser.dart:2484:13)
parseFormalParameters(f, MemberKind.TopLevelMethod) (package:front_end/src/fasta/parser/parser.dart:1153:15)
parseFormalParametersRest((, MemberKind.TopLevelMethod) (package:front_end/src/fasta/parser/parser.dart:1216:12)
listener: beginFormalParameters((, MemberKind.TopLevelMethod) (package:front_end/src/fasta/parser/parser.dart:1227:14)
This output should obviouslys not be committed, but is great for debugging.
Change-Id: I42db55ff928bde783d652b6338b54e6dba1550db
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121326
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
+ reduce ModifierBuilder interface
+ introduce ConstructorScope(Builder) and AmbiguousMemberBuilder
+ reduce use of Builder.target by using the more ligthweight MemberBuilder interface
Change-Id: I6366559f7c85bbd3224ef906505a67a379092686
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121063
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
This moves the logic for detecting the patterns `variable == null` and
`null == variable` into flow analysis, so that they don't need to be
replicated in each client. It also opens the door to potential future
improvements (e.g. allowing `x == expr` to promote `x` to non-nullable
if expr has a non-nullable type).
Change-Id: I51fd9df822e3df1eb8bad5884f767c8b61c496ef
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120934
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This will allow us to store more varied context information (which
we'll need to do in order to generalize the handling of `==` in a
follow-up CL).
Change-Id: I85a19004dd4d4845d6fce7d8c0ce3cf0bbec8120
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120933
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Rather than suppress all promotions for variables written to in
closures, we track whether a closure might exist that captures a write
to a variable, and only suppress promotions once such a closure
exists. This is consistent with what is proposed in
https://github.com/dart-lang/language/pull/473.
Contains a repro of #38791.
Change-Id: I4683581908703b510a3231b8fa8ed697121b09da
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120680
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Previously, we considered a variable to be captured by a closure if a
write to that variable occurred anywhere inside a local function. But
that was overly broad; it meant that we incorrectly classified all
written-to local variables of a local function to be captured.
This CL makes the AssignedVariables logic aware of variable
declaration sites, so that it only considers a variable to be captured
if it is written to at a lower level of local function nesting than
its declaration. As a side bonus, it means that it can now exclude
out-of-scope variables from all sets of closed-upon and written-to
variables, which should make flow analysis faster by preventing it
from spending a lot of time accounting for variables that aren't
visible.
It also adds tracking of the set of all variables written to and
captured within each top level function.
This partially reverts commit 55466fd3cc.
Change-Id: Ibcd6476445addebed13cfc5ecc470d644e519148
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120800
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Add an incremental serializer that can be used to avoid re-serializing
the same thing again and again.
It does this by grouping libraries into Components / bundles,
serializing them individually and using the concatenated dill feature to
output the wanted data --- just potentially faster if we had the data
in cache.
Note that the serialized output might contain *more* than the input given
if we cached the wanted data into a bigger bundle.
The output will always be "closed" though, i.e. if the stuff that is
included that is too much added a new dependency, that dependency will be
included as well.
This should generally make it safe, although one can imagine situations
where it could pull in lots of dependencies that it wouldn't otherwise
have.
It is being driven by the incremental compiler which makes sure to
invalidate the cache when the data changes.
Except for situations where the libraries are changed externally after
being serialized, but before being serialized again, where one then wants
the updated library serialized, the feature should be safe.
Change-Id: I2a504abe6dbb68434c3b04abff13480ef72a6a6e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120786
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
Prior to this change, loading the sdk dill twice for instance would
result in additional exports as well as parameter counts doubling,
essentially destroying the result.
Change-Id: I4d694bec1926d6df6572e9bb36e8a88ec0822e27
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120785
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Previously we created flow analysis on entry to a function/method's
block, but that meant that we would miss promotions that occurred
inside constructor initializers.
Contains test cases for #38761
Change-Id: I566fb77173d9ce6b3aae994c525955f3cbe06fff
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120503
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>