We should consider the nullability of the right hand side of a typedef
to be "never", since a `?` is not allowed on there. Instead, we
should allow each use of a typedef to have its own independent
nullability.
Fixes a bug wherein we would erroneously migrate code like this:
typedef F<T> = int Function(T);
F<String> f = null;
Into the following:
typedef F<T> = int Function(T)?;
F<String>? f = null;
(Note the bogus `?` after `int Function(T)`).
Change-Id: I8535645303fc644c73617684b8bb3488462589ee
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136900
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
This CL adds the following functionality to the migration postmortem
utility:
- The "steps" subcommand now prints both upstream and downstream
migration steps (previously it only printed downstream steps).
- The "files" subcommand lists all input files for which at least one
decorated type was stored.
- The "decorations" subcommand lists all the decorated types for a
given input file.
- The "node" subcommand shows details about a single node, including
any edges connected to it.
Change-Id: I034f13ffd7efa340e1cc50bf9039372f78da5027
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136840
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
This CL fixes several minor bugs:
- In info_builder.dart, we were trying to apply SourceInformation from
the defining library to all its parts.
- In NnbdMigrationTestBase, we were trying to fully migrate each file
before processing any other files. We need to prepare each input,
then process each input, then finalize each input.
- In NodeBuilder, we were failing to send part file sources to
NullabilityGraph.migrating(). As a result, methods declared in part
files were being treated as already migrated, so they were getting
the wrong kinds of nullability nodes.
- In _ProvisionalApiTestBase, we were sometimes visiting parts before
discovering what libraries they were part of, causing inconsistent
resolution results.
I'm hoping this will be sufficient to address
https://github.com/dart-lang/sdk/issues/40670.
Change-Id: I07d693b31b6cf64bc6f72126f5ef4792b29e5029
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136521
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Usually when migration removes dead code it can just delete it
(e.g. because it's removing a statement from a block and blocks can
contain any number of statements). However, in certain contexts dead
code must be replaced with something else, such as an empty statement.
Change-Id: I65faf017897215d750395dc78a2bf8a157d8dce0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136441
Reviewed-by: Janice Collins <jcollins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This was causing 9k exceptions and slowing the flutter migration from
2:40 to 14:40.
There are 52 elements that don't get a decorated type in flutter due to
the abnormal usage of part files for the animated icons test.
The re-resolution stage of fixbuilder would then try to get the
finalType of these elements, but no decorated type for them exists, so
it would throw this exception. However, since the throw expression
stringifys the element, the element would go back to the hooks that try
to turn it into a finalType, which results in the same failure, until a
stack overflow.
Change-Id: Ib4c4746728e8bc6e583e133e91dcc0ba83e1b911
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136040
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Mike Fairhurst <mfairhurst@google.com>
Tests currently pass, so we can close that bug. However, if for some
reason it becomes an issue such that these tests fail, they will link to
a bug with detailed info on a potential cause.
Bug: 40625
Change-Id: I212eb5401622a189de4998247b0ff521077e30e3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135763
Reviewed-by: Paul Berry <paulberry@google.com>
The target of a property access can be null if it is a cascade. If that
access is then modified, fix aggregator gets a NPE. This issue is not
true for index & method calls, same fix applies.
Change-Id: I98eac3c8f7eba5300b30ff366ee227430726440c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135963
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Mike Fairhurst <mfairhurst@google.com>
A compound node represents a logical OR ("this node is nullable if and
only if one or more of its components is nullable"). Therefore, if
*all* of the components of a compound node have non-null intent, we
should consider the compound node itself to have non-null intent.
This fixes a problem that was preventing the migration tool from
respecting a "/*!*/" hint applied to the type parameter of a typedef.
Change-Id: Iec2f9d6968378707ba692be7b97f750cf53a8b85
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135786
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Usually we have good information from the nullability graph about why
we need to insert a cast, but sometimes we don't. For example, when a
cast needs to be inserted because NNBD doesn't allow implicit
downcasts, we often can't give any additional information beyond "a
cast is needed here now".
We allow info to be null in these cases to avoid an assertion failure.
Fixes https://github.com/dart-lang/sdk/issues/40533.
Change-Id: I7639374f92820faf04bda2aeda96d0e38f07e8d5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135161
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
There were two problems:
1. An info object isn't being properly passed to
NodeChangeForExpression, causing an assertion failure during the
FixAggregator stage. I've modified the assertion check so that it
happens earlier, during the FixBuilder, so that the exception is
caught by permissive mode logic and doesn't cause a hard crash.
I'll work on fixing the assertion in a follow-up CL.
2. The hack described in https://github.com/dart-lang/sdk/issues/40536
was causing a bogus assertion failure in
_PassThroughBuilderImpl._checkParenLogic. I've weakened the
assertion slightly so that for now, the hack won't cause trouble.
See the issue for more information about what's happening--this
should be cleaned up eventually but it's probably not high
priority.
Bug: https://github.com/dart-lang/sdk/issues/40533
Change-Id: Iee832fbd07e54b02d2c52f79a097ff9d973cda9a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134980
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Under NNBD rules, certain function literals have their types inferred
as `Object?` instead of `dynamic`. We need to add explicit `dynamic`
to prevent follow-on errors if those parameters are used in a dynamic
fashion.
Change-Id: I12bfd3a3da2bda1ae11b01a5d029dbea3d512cb6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134567
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
DartType.== implementations ignore nullability if the flag is not true.
TypeSystem APIs eliminate nullability from types before doing anything.
Internally analyzer continues using actual nullability for types.
Package nnbd_migration opted into NullSafetyUnderstandingFlag.
Bug: https://github.com/dart-lang/sdk/issues/40500
Change-Id: Ifeea28c01adf1dc59ed2da675b4a62c6334d529a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134865
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Previously, if a function literal was used in a context where a
function returning non-null was expected, but the function literal
might return null, the migration tool inserted a cast that was
guaranteed to fail. Now it propagates non-null intent into the
function literal, so that the appropriate null checks happen inside
the function literal.
Change-Id: Ia62d18bc3b9955e84b09b846ea913607b305677d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134504
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This CL extends ElementTypeProvider so that it also tracks type
parameter bounds. This allows the FixBuilder to reason correctly
about the what generic function types will look like after migration,
and that in turn prevents it from trying to add unnecessary casts.
Change-Id: I3c909a3b5ba14bf9f2aad4e58d0981c1b7b5bdd2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134412
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
We now track decorated type parameter bounds similarly to how we track
ordinary type parameter bounds in the FixBuilder, by having a single
static instance of a DecoratedTypeParameterBounds class that keeps
track of the mapping.
Change-Id: I49196e8a506ca8765857b3d47a355b7aaaa1918e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134411
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Previously, each piece of analyzer code needed during the FixBuilder
stage of migration needed to use the ElementTypeProvider interface to
access element types (rather than reading the types from the elements
directly), in order to ensure that the proper post-migration types
were used when building fixes. This required a lot of plumbing, and
there was a high risk that we would accidentally fail to use the
indirection mechanism in a key location and access the elements
directly.
This CL changes the approach so that the ElementImpl classes
themselves are responsible for indirecting through
ElementTypeProvider. This means that we can back out all the
plumbing, and there is no risk of accidentally failing to use the
indirection mechanism.
Change-Id: Ic1a0acc37f0350fc13b487f73fc1ad5225d7a090
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134360
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
When adding a cast to a function expression like `() => null`, we need
to add parentheses, so that we produce `(() => null) as Type`, rather
than `() => null as Type`, which makes the cast appear to apply to the
function body expression.
Change-Id: Ib5ae93df5b840a832c10941e47fa092a4f764eea
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134044
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
This required adding logic to the `TypeParameterType` case of the
`toFinalType` function, so that we look up the decorated type of the
type parameter bound, and convert it to a final type as well.
(Previously we were just using the bound stored in the element model,
which was in many cases the bounds from prior to migration, and hence
it was a `*` type so it behaved as though it was non-nullable).
This required moving `toFinalType` into the `Variables` class so that
it could look up the decorated types of type parameter bounds.
Fixes#40355.
Change-Id: I53c2636aef6954500589e924b9755a297c2b30f9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134061
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Two minor fixes:
- Ensure that the immutable nodes `always` and `never` are always
drawn with the `shape=none` attribute. (Previously, the first time
we encountered an immutable node we would draw it in the style of a
mutable node, which made things very confusing).
- Add a space before `style=filled` in the graphviz output.
Previously we would output things like
`n21 [label="type(13) (ordinary nullable)"style=filled]`,
which graphviz seems to do ok with but seems inadvisable.
Change-Id: Iefcb4005c9bb2e24ae8d80552e5e4a23ec062c56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133868
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>