Migration: fix crashes with extension Foo<T extends ...> on T

Change-Id: I3a8f1be4f52a6a49bb57ab032fef668482f5acf6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151002
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
Paul Berry 2020-06-12 18:21:15 +00:00 committed by commit-bot@chromium.org
parent 6f4bc6a9be
commit 43131b575e
2 changed files with 47 additions and 1 deletions

View file

@ -236,7 +236,8 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
} else {
assert(enclosingElement is ExtensionElement);
final extensionElement = enclosingElement as ExtensionElement;
final extendedType = extensionElement.extendedType;
final extendedType =
_typeSystem.resolveToBound(extensionElement.extendedType);
if (extendedType is InterfaceType) {
if (extensionElement.typeParameters.isNotEmpty) {
substitution = _decoratedClassHierarchy
@ -743,6 +744,7 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
DecoratedType visitExtensionDeclaration(ExtensionDeclaration node) {
visitClassOrMixinOrExtensionDeclaration(node);
_dispatch(node.typeParameters);
_dispatch(node.extendedType);
return null;
}
@ -2917,6 +2919,8 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
NullabilityNode.forInferredType(
target.typeArgument(index++))))
.toList());
} else if (type is TypeParameterType) {
return DecoratedType(type, NullabilityNode.forInferredType(target));
} else {
_unimplemented(node, 'extension of $type (${type.runtimeType}');
}

View file

@ -2082,6 +2082,48 @@ void g() => f(null);
await _checkSingleFileChanges(content, expected);
}
Future<void> test_extension_on_type_param_implementation() async {
var content = '''
abstract class C {
C _clone();
}
extension Cloner<T extends C> on T {
T clone() => _clone() as T;
}
''';
var expected = '''
abstract class C {
C _clone();
}
extension Cloner<T extends C> on T {
T clone() => _clone() as T;
}
''';
await _checkSingleFileChanges(content, expected);
}
Future<void> test_extension_on_type_param_usage() async {
var content = '''
abstract class C {
C _clone();
}
extension Cloner<T extends C> on T {
T clone() => throw Exception();
}
C f(C c) => c.clone();
''';
var expected = '''
abstract class C {
C _clone();
}
extension Cloner<T extends C> on T {
T clone() => throw Exception();
}
C f(C c) => c.clone();
''';
await _checkSingleFileChanges(content, expected);
}
Future<void> test_field_final_uninitalized_used() async {
var content = '''
class C {