Migration: Work around null reference exception with complex type parameters.

Change-Id: Ib3f081225f9ec7cb8714ca0aa789d4dea1a378db
Bug: https://github.com/dart-lang/sdk/issues/43945
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/169252
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
Paul Berry 2020-10-28 14:01:57 +00:00 committed by commit-bot@chromium.org
parent a777d2b798
commit 9181570513
2 changed files with 42 additions and 2 deletions

View file

@ -420,8 +420,21 @@ class DecoratedType implements DecoratedTypeInfo {
var typeFormal = typeFormals[i];
var oldDecoratedBound =
DecoratedTypeParameterBounds.current.get(typeFormal);
var newDecoratedBound = oldDecoratedBound._substitute(substitution,
undecoratedResult.typeFormals[i].bound ?? oldDecoratedBound.type);
var undecoratedResult2 = undecoratedResult.typeFormals[i].bound;
if (undecoratedResult2 == null) {
if (oldDecoratedBound == null) {
assert(
false, 'Could not find old decorated bound for type formal');
// Recover the best we can by assuming a bound of `dynamic`.
oldDecoratedBound = DecoratedType(
DynamicTypeImpl.instance,
NullabilityNode.forInferredType(
NullabilityNodeTarget.text('Type parameter bound')));
}
undecoratedResult2 = oldDecoratedBound.type;
}
var newDecoratedBound =
oldDecoratedBound._substitute(substitution, undecoratedResult2);
if (identical(typeFormal, undecoratedResult.typeFormals[i])) {
assert(oldDecoratedBound == newDecoratedBound);
} else {

View file

@ -4583,6 +4583,33 @@ f() {
await _checkSingleFileChanges(content, expected);
}
Future<void> test_many_type_variables() async {
try {
assert(false);
} catch (_) {
// When assertions are enabled, this test fails, so skip it.
// See https://github.com/dart-lang/sdk/issues/43945.
return;
}
var content = '''
void test(C<int> x, double Function<S>(C<S>) y) {
x.f<double>(y);
}
class C<T> {
U f<U>(U Function<V>(C<V>) z) => throw 'foo';
}
''';
var expected = '''
void test(C<int> x, double Function<S>(C<S>) y) {
x.f<double>(y);
}
class C<T> {
U f<U>(U Function<V>(C<V>) z) => throw 'foo';
}
''';
await _checkSingleFileChanges(content, expected, warnOnWeakCode: true);
}
Future<void> test_map_nullable_input() async {
var content = '''
Iterable<int> f(List<int> x) => x.map((y) => g(y));