Skip to content

Commit 43131b5

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
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 <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 6f4bc6a commit 43131b5

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

pkg/nnbd_migration/lib/src/edge_builder.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,8 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
236236
} else {
237237
assert(enclosingElement is ExtensionElement);
238238
final extensionElement = enclosingElement as ExtensionElement;
239-
final extendedType = extensionElement.extendedType;
239+
final extendedType =
240+
_typeSystem.resolveToBound(extensionElement.extendedType);
240241
if (extendedType is InterfaceType) {
241242
if (extensionElement.typeParameters.isNotEmpty) {
242243
substitution = _decoratedClassHierarchy
@@ -743,6 +744,7 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
743744

744745
DecoratedType visitExtensionDeclaration(ExtensionDeclaration node) {
745746
visitClassOrMixinOrExtensionDeclaration(node);
747+
_dispatch(node.typeParameters);
746748
_dispatch(node.extendedType);
747749
return null;
748750
}
@@ -2917,6 +2919,8 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
29172919
NullabilityNode.forInferredType(
29182920
target.typeArgument(index++))))
29192921
.toList());
2922+
} else if (type is TypeParameterType) {
2923+
return DecoratedType(type, NullabilityNode.forInferredType(target));
29202924
} else {
29212925
_unimplemented(node, 'extension of $type (${type.runtimeType}');
29222926
}

pkg/nnbd_migration/test/api_test.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,6 +2082,48 @@ void g() => f(null);
20822082
await _checkSingleFileChanges(content, expected);
20832083
}
20842084

2085+
Future<void> test_extension_on_type_param_implementation() async {
2086+
var content = '''
2087+
abstract class C {
2088+
C _clone();
2089+
}
2090+
extension Cloner<T extends C> on T {
2091+
T clone() => _clone() as T;
2092+
}
2093+
''';
2094+
var expected = '''
2095+
abstract class C {
2096+
C _clone();
2097+
}
2098+
extension Cloner<T extends C> on T {
2099+
T clone() => _clone() as T;
2100+
}
2101+
''';
2102+
await _checkSingleFileChanges(content, expected);
2103+
}
2104+
2105+
Future<void> test_extension_on_type_param_usage() async {
2106+
var content = '''
2107+
abstract class C {
2108+
C _clone();
2109+
}
2110+
extension Cloner<T extends C> on T {
2111+
T clone() => throw Exception();
2112+
}
2113+
C f(C c) => c.clone();
2114+
''';
2115+
var expected = '''
2116+
abstract class C {
2117+
C _clone();
2118+
}
2119+
extension Cloner<T extends C> on T {
2120+
T clone() => throw Exception();
2121+
}
2122+
C f(C c) => c.clone();
2123+
''';
2124+
await _checkSingleFileChanges(content, expected);
2125+
}
2126+
20852127
Future<void> test_field_final_uninitalized_used() async {
20862128
var content = '''
20872129
class C {

0 commit comments

Comments
 (0)