Since `this` is essentially a variable in extensions, it should be
treated similarly to variables in terms of inference of non-null
intent; for example, if an extension declaration contains a a method
that unconditionall dereferences `this` (either implicitly or
explicitly), that's a good indication that the user probably doesn't
intend for the extension to be applied to nullable types.
Fixes#44675.
Bug: https://github.com/dart-lang/sdk/issues/44675
Change-Id: I004328f5b1fd6710954363c07f4e9db6bc6ac2cd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/180268
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
After a variable is write captured, references to it should no longer
be considered to express non-null intent, because we can no longer
guarantee that an initially null value of the variable would
definitely lead to an exception.
Change-Id: I44c65350291a4c44cdb4b19529b13149d8170e34
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/180100
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Currently the migrator can add `@required` from the preview, which will crash
the preview upon rerunning, if package:meta is not imported.
This change instead adds a /*required*/ hint when meta is not imported.
Additionally, /*required*/ is understood by the migrator just as if it were
`@required`.
Fixes https://github.com/dart-lang/sdk/issues/43751
Change-Id: I1ea532246b956feacedd179146372b13c65003df
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/169900
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Well not quite all; migration_cli_test tests are a bit of a different
beast so I am going to tackle them separately. But this fixes over
1000 test failures, and should clean up test output for further
debugging of the flip CL.
Each test file needs to be in a package with a package config file
which spells out that it is _opted out_ of null safety.
Bug: https://github.com/dart-lang/sdk/issues/43883
Change-Id: I583f66119df57031fd80824111923e15e0f91782
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/168900
Reviewed-by: Leaf Petersen <leafp@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
This logic allows us to migrate code like this:
int firstEven(Iterable<int> values)
=> values.firstWhere((i) => i.isEven, orElse: () => null);
Into:
import 'package:collection/collection.dart' show IterableExtension;
int? firstEven(Iterable<int> values)
=> values.firstWhereOrNull((i) => i.isEven);
Rather than the default behavior, which would migrate it to:
int? firsteven(Iterable<int?> values)
=> values.firstWhere((i) => i!.isEven, orElse: () => null);
(The new migration is far superior because it doesn't require the
input iterable to accept null).
This functionality is disabled at the moment, because:
- The changes it makes don't show up properly in the web preview.
- The pubspec is not yet properly updated.
I will address these issues in follow-up CLs and then enable the
feature.
Change-Id: I96f3b12d682c586631920b38406bad6aa3f4789e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/168500
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
I'm looking into enabling NullSafetyUnderstandingFlag in the next
analyzer breaking change.
test_function_void_to_function_object() fails, and it seems that
the test class should use legacy TypeProvider, because `Object` is not
assignable to `void`, but `Object*` is.
Change-Id: Ib867e0eec7a387ed3ed1379a7ef34a58b16e54ae
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/168125
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Fixing the test that's causing the Windows bot to fail required updating
the MockSdk, which cause a lot of other changes. I would have done this
in two separate CLs if I'd known how big this was going to get, but I'm
hoping it isn't too big.
Change-Id: Idee56bab5e73a78ab7857e81177090493aa08b40
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151874
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Fixes https://github.com/dart-lang/sdk/issues/38291
This change also involves moving the "package" where test sources are
written and analyzed; It used to be /home/test (or /project in some
places); and a pubspec.yaml was written (or a .packages file) which
specified the package's name was "test". However, this conflicts with
adding an entry for a mock copy of the actual _test_ package. A
.packages file cannot have two entries for a package named "test", so
the package where all test sources are written is changed to "tests"
(located at /home/tests).
Change-Id: I462b88a814931dc2d4f1e72d07e3daf64768a399
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144994
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
This change adds the ability to detect when one branch of a
conditional expression is weak-only due to nullability. For example,
in the following code:
int f(int/*!*/ i) => i == null ? g(null) : i;
int g(int j) => ...;
the call to `g` can only happen in weak checking mode. The migrator
also now understands that j only needs to be nullable if i is
nullable.
Fixes#41555.
Partially addresses #41551.
Bug: https://github.com/dart-lang/sdk/issues/41555
Change-Id: I02c9c3072f0104db0f1a5b432fb1f2f8f06d5282
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/144120
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Previously, if we migrated a code snippet like this:
void f(int/*?*/ i) {
/*late*/ int j = i/*!*/;
}
the migration result would leave the hints and add the hinted text,
resulting in:
void f(int?/*?*/ i) {
/*late*/ late int j = i!/*!*/;
}
We now simply remove the `/*` and `*/` surrounding each hint (with
whitespace corrections as needed), to produce:
void f(int? i) {
late int j = i!;
}
Change-Id: Ic4e1216cb4693d73d71c9ab1a37d5cc15b8ef334
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/143460
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Previously, when handling an override such as:
abstract class A {
int/*?*/ f();
}
class C implements A {
f() => 0;
}
we would create a union edge between the implicit return type of C.f
and the explicit return type of A.f. This was a problem because
nullability information can propagate bidirectionally through union
edges, so it could result in types unnecessarily becoming nullable,
e.g.:
abstract class A {
int/*?*/ f();
}
abstract class B {
int f(); // Should not need to be made nullable
}
class C implements A, B {
f() => 0;
}
This CL fixes the problem by just making ordinary unidirectional edges
for overrides involving inferred types.
Change-Id: I63a5f1f640b5543fcf39304087592e984aa66694
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/141853
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Previously, null check hints were only affecting the behavior of
EdgeBuilder, which meant that we handled simple cases like:
int f(int/*?*/ x) => x/*!*/;
(because the EdgeBuilder wouldn't build an edge from the type of `x`
to the return type of `f`, so the return type of `f` would be
non-nullable int, and hence the FixBuilder would insert a `!` in order
to prevent an error).
But if there were some *other* reason for the destination type to be
nullable, then no `!` would get inserted.
This CL adds explicit logic to the FixBuilder to ensure that a `/*!*/`
hint causes a `!` to be inserted whether it's necessary or not.
Change-Id: I283bb9793d8d01408333f5b56562286bf19d8773
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/140904
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
This establishes the base functionality. A lot of follow-up work is
needed from here:
- Each trace should have an entry at the top of it pointing to the
thing that was made nullable.
- The source code links in traces don't include lengths, so we can't
highlight whole identifiers when the user clicks on a link.
- Description strings are currently generated by running toString() on
the individual nullability nodes and edges, resulting in long-winded
and useless descriptions.
Change-Id: Ibb370bae6bedc7a8c86092462785023002a48ac3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/138481
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
The principal cause may be displayed by invoking the "postmortem" tool
using the "trace" subcommand, followed by the id of the node for which
a trace is desired.
Change-Id: I5868b4bc979320bb46698b02c7b43b317205c487
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/137429
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
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>