Skip to content

Commit

Permalink
[nnbd_migration] Fix TypeParameterType asInstanceOf where valid.
Browse files Browse the repository at this point in the history
Change-Id: I033b378d0e87ead2bacad27d71a0c696904d8e15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/128985
Commit-Queue: Mike Fairhurst <mfairhurst@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
  • Loading branch information
MichaelRFairhurst authored and commit-bot@chromium.org committed Dec 20, 2019
1 parent 4dd9734 commit 4681868
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 2 deletions.
20 changes: 18 additions & 2 deletions pkg/nnbd_migration/lib/src/decorated_class_hierarchy.dart
Expand Up @@ -28,9 +28,10 @@ class DecoratedClassHierarchy {

/// Retrieves a [DecoratedType] describing how [type] implements [superclass].
///
/// If [type] is not an interface type, or it does not implement [superclass],
/// raises an exception.
/// If the [type] is a [TypeParameterType], it will be resolved against its
/// bound.
DecoratedType asInstanceOf(DecoratedType type, ClassElement superclass) {
type = _getInterfaceType(type);
var typeType = type.type as InterfaceType;
var class_ = typeType.element;
if (class_ == superclass) return type;
Expand Down Expand Up @@ -104,4 +105,19 @@ class DecoratedClassHierarchy {
}
return decorations;
}

DecoratedType _getInterfaceType(DecoratedType type) {
var typeType = type.type;
if (typeType is InterfaceType) {
return type;
}

if (typeType is TypeParameterType) {
final innerType = _getInterfaceType(
_variables.decoratedTypeParameterBound(typeType.element));
return type.substitute({typeType.element: innerType});
}

throw ArgumentError('$type is an unexpected type');
}
}
103 changes: 103 additions & 0 deletions pkg/nnbd_migration/test/edge_builder_test.dart
Expand Up @@ -2138,6 +2138,38 @@ void f(List<int> l) {
hard: false);
}

test_for_each_on_type_parameter_type() async {
await analyze('''
void f<T extends List<int>>(T l) {
for (int i in l) {}
}
''');
// TODO(mfairhurst): fix this: https://github.com/dart-lang/sdk/issues/39852
//assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
assertEdge(decoratedTypeAnnotation('T l').node, never, hard: true);
assertEdge(
substitutionNode(
decoratedTypeAnnotation('int>').node, inSet(pointsToNever)),
decoratedTypeAnnotation('int i').node,
hard: false);
}

test_for_each_on_type_parameter_type_bound_bound() async {
await analyze('''
void f<T extends R, R extends List<int>>(T l) {
for (int i in l) {}
}
''');
// TODO(mfairhurst): fix this: https://github.com/dart-lang/sdk/issues/39852
//assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
assertEdge(decoratedTypeAnnotation('T l').node, never, hard: true);
assertEdge(
substitutionNode(
decoratedTypeAnnotation('int>').node, inSet(pointsToNever)),
decoratedTypeAnnotation('int i').node,
hard: false);
}

test_for_each_with_declaration() async {
await analyze('''
void f(List<int> l) {
Expand Down Expand Up @@ -5670,6 +5702,77 @@ void f(C<int> c) {}
hard: true);
}

test_type_parameter_method_call_bound() async {
await analyze('''
class Foo {
void bar(int x) {}
}
void f<T extends Foo>(T t) {
t.bar(null);
}
''');
assertEdge(decoratedTypeAnnotation('T t').node, never, hard: true);
// TODO(mfairhurst): fix this: https://github.com/dart-lang/sdk/issues/39852
//assertEdge(decoratedTypeAnnotation('Foo>').node, never, hard: true);
assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int x').node,
hard: false);
}

test_type_parameter_method_call_bound_bound() async {
await analyze('''
class Foo {
void bar(int x) {}
}
void f<T extends R, R extends Foo>(T t) {
t.bar(null);
}
''');
assertEdge(decoratedTypeAnnotation('T t').node, never, hard: true);
// TODO(mfairhurst): fix this: https://github.com/dart-lang/sdk/issues/39852
//assertEdge(decoratedTypeAnnotation('Foo>').node, never, hard: true);
assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int x').node,
hard: false);
}

test_type_parameter_method_call_bound_generic() async {
await analyze('''
class Foo<T> {
void bar(int x) {}
}
void f<T extends Foo<dynamic>>(T t) {
t.bar(null);
}
''');
assertEdge(decoratedTypeAnnotation('T t').node, never, hard: true);
// TODO(mfairhurst): fix this: https://github.com/dart-lang/sdk/issues/39852
//assertEdge(decoratedTypeAnnotation('Foo>').node, never, hard: true);
assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int x').node,
hard: false);
}

test_type_parameter_method_call_bound_generic_complex() async {
await analyze('''
class Foo<T> {
void bar(T x) {}
}
void f<R extends Object, T extends Foo<R>>(T t) {
t.bar(null);
}
''');
assertEdge(decoratedTypeAnnotation('T t').node, never, hard: true);
// TODO(mfairhurst): fix this: https://github.com/dart-lang/sdk/issues/39852
//assertEdge(decoratedTypeAnnotation('Foo>').node, never, hard: true);
assertEdge(
inSet(alwaysPlus),
substitutionNode(decoratedTypeAnnotation('R>').node,
decoratedTypeAnnotation('T x').node),
hard: false);
}

test_type_parameterized_migrated_bound_class() async {
await analyze('''
import 'dart:math';
Expand Down

0 comments on commit 4681868

Please sign in to comment.