To avoid inserting unnecessarily complex casts, we want to normalize a
type like `void Function<T extends Object?>()` to the equivalent `void
Function<T>()`.
Change-Id: Ied10e7735511b732eaeca027e621b4ef6997df59
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133820
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This eliminates a lot of really noisy boilerplate in the upcoming
FantasyRepo implementation. The test only verifies that the pathway
works, we rely on MultiFutureTracker working to actually restrict
properly.
Change-Id: Ia88d0b24dd739ab1cd4a661325214395bf37eef3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133742
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Janice Collins <jcollins@google.com>
Previously, FixAggregator provided one NodeChange-derived class for
each possible kind of fix; if multiple fixes had to be made to a
single AST node, its client (FixBuilder) was required to nest them in
the appropriate order. FixBuilder accomplished this by carefully
controlling the order in which it decided on fixes. Unfortunately,
this careful control of order is becoming burdensome for FixBuilder to
maintain.
With this change, the class hierarchy of NodeChange mirrors the class
hierarchy of AstNode, with different fields for each possible kind of
fix. This means that FixBuilder can decide on fixes in whatever order
is convenient.
Change-Id: I1c79cfc37b6289051b3927c67867b77a1dbb5ebf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133541
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
I realized that I can use the same "pass through" infrastructure for
these kinds of edits. This should help prepare for a future CL in
which we can aggregate together more complex changes, such as
introducing an "as" cast at the same time as changing `?.` into `.`.
Change-Id: Ie3af07a3563c44d62d4ed34d2a477eef6fae358f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133540
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Since https://dart-review.googlesource.com/c/sdk/+/133422 has
introduced the possibility that a node previously marked as
non-nullable would later be marked as nullable, we need to make sure
that doesn't happen for types that have been explicitly marked as
non-nullable using a "/*!*/" hint, or types that are non-nullable in
an already-migrated library.
This required refactoring the state of nullability nodes slightly.
Nodes can now be in six states:
1. Non-nullable (previously called "undetermined")
2. Non-nullable, with non-nullable intent (previously called
"nonNullable")
3. Nullable
4. Nullable, with non-nullable intent (previously indistinguishable
from 3)
5. Exact nullable
6. Exact nullable, with non-nullable intent (previously
indistinguishable from 5)
To allow all these states to be distinguished, we separate the state
into two orthogonal parts: a "nullability" part and a "non-null
intent" part.
Change-Id: I588a2e63eaa76e3992fdfbaaa2e8b212cc1f60d1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133440
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
It didn't wind up being used, and its presence limits our ability to
modify the graph propagation algorithm (which I plan to do in a
follow-up CL).
Change-Id: I48a9b879f25295075e8d95eb3fb0185839303957
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133425
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Shifted some minor things around in the design as well -- particularly
the symlink is moved to being owned by the workspace as not all
workspace implementation will create symlinks in the original directory.
I've also dropped most of the public interface to FantasyWorkspace.
Will add that back in when I'm more sure what it will be.
Change-Id: I19d1b1c8ad4063868ff7c10869c4561d4db64bf2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133435
Commit-Queue: Janice Collins <jcollins@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
This prevents a non-null assertion in a callback function from marking
the parameter type as non-nullable, if that would make the callback
function fail to meet the requirements of its use site. For example,
when migrating:
f(List<int/*?*/> myList) => myList.map((int x) => x + 1);
We previously would produce:
f(List<int?> myList) => myList.map((int x) => x + 1);
(Which would fail immediately due to the callback `(int x) => x + 1`
not accepting `int?`). We now produce:
f(List<int?> myList) => myList.map((int? x) => x! + 1);
(Which only fails if there is actually a null value in the list,
matching the behavior of the code prior to migration).
Addresses another manifestation of
https://github.com/dart-lang/sdk/issues/38699.
Change-Id: Iffe9fbdace00ff1edea0f6d125c86b06fad7bbcb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133423
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Previously, graph propagation occurred in three steps:
1. Mark any nodes connected to `always` by union edges as nullable.
2. Mark any nodes connected to `never` by hard or union edges as
non-nullable, but do not change any nodes marked by #1.
3. Mark any nodes connected to `always` as nullable, but do not change
any nodes marked by #1 or #2 (with additional processing for
substitution nodes).
This approach had the advantage that once a node is marked as nullable
or non-nullable, it is never changed, which made reasoning about the
algorithm a bit easier. But in an upcoming CL I'll need to modify the
algorithm in a way that's incompatible with this approach.
This CL introduces the notion that some edges are "checkable" and some
aren't (an edge is "checkable" if it's ok for graph propagation to
leave it unsatisfied, because the fix builder can insert a null
check). At the moment all edges are considered checkable except for
union edges, but that will change in future CLs in order to address
https://github.com/dart-lang/sdk/issues/38699.
The algorithm is now:
1. Mark any nodes connected to `never` by hard or union edges as
non-nullable.
2. Mark any nodes connected to `always` as nullable, but only change
nodes marked by #1 if necessary to satisfy uncheckable edges (with
additional processing for substitution nodes).
An alternative way of thinking of this algorithm is that hard edges
reflect user intentions that we should try to satisfy if we can, but
which shouldn't take priority over creating output that is free of
static errors. During phase 1, we propagate hard edges to find all
the nodes the user *intends* to make non-nullable. During phase 2, we
propagate nullability, respecting user intention where we can, and
overriding it where we can't.
Change-Id: Ie3f9d9ee66f407f9d4916f7259e7f50a82ebb2bb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133402
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
This serves two purposes:
1. It makes it easier to be confident that we're resetting the
necessary state when re-running graph computation in
`NullabilityGraph.update`.
2. I'm planning some changes to the graph propagation algorithm (in an
upcoming CL). Having the propagation state separate from the rest
of the graph state will make it easier to reason about these
changes.
Change-Id: I5e101bbce6e5ad382dd754bfbb9b72e20df23fd1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133337
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
The visitSimpleIdentifier method was failing to return a DecoratedType
for the case where the identifier was `void`.
In practice this didn't matter, since the only time the type returned
from visitSimpleIdentifier is used is when the the identifier is used
as an expression, and `void` can't be used an expression (i.e. `var
voidType = void;` is illegal).
Nonetheless, it's nice to silence the warning, and it seems like it
increases safety to return a value from visitSimpleIdentifier in all
cases.
Change-Id: I239b98b9e5932195e6884738728d26d86c6ab519
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133336
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Moved AnnotationTracker to CompletenessTracker which defers work to
AnnotationTracker and new class TypeNameTracker.
This passes on flutter and p1/g1 packages.
Change-Id: I5c92ed287d4d35b2b2f0d21846db197e24584dc5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133227
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Mike Fairhurst <mfairhurst@google.com>
When migrating, we'll need to change some null-aware property accesses
and method calls to non-null-aware (due to the fact that the receiver
is non-nullable, or due to the new `?.` shortcut rules), so when
migration re-resolves, it will need to be able to override
resolution's determination of whether a given property access or
method call is null-aware.
Change-Id: I411f43fb937431e757d4dd9b968874db84158e47
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133240
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>