Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 191340
b: refs/heads/beta
c: c604e58
h: refs/heads/master
  • Loading branch information
stereotype441 authored and commit-bot@chromium.org committed Aug 27, 2019
1 parent fee326e commit 1e3c17e
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ refs/tags/2.3.0-flutter-1.5.4-hotfix.1: a1668566e563aef64025d0af88a099cbbe847b7e
refs/tags/2.3.1: 929b013ddc83a013b49a98fc28b6b503a972bddd
refs/tags/2.3.1-dev.0.0: 1d1742efd39cd4762b844b510acf8c2f1fa6604e
refs/tags/2.3.2-dev.0.0: c567183bac8a895014d79cd3bf1d8908d45547d6
refs/heads/beta: c7ac27bf504cca030881208eb0b056a5a7ff93c2
refs/heads/beta: c604e58a9b387856a630391aa0ec88acc010b88e
refs/heads/sjindel.mep: b113b36c157cf54b257e82550e9bbde16f05ad8d
refs/tags/2.3.2: f7ab96133aa79301daf812ef40b33c99d8ad1495
refs/tags/2.3.2-dev.0.1: ef57e27c9798b54a54e9a1f74b1bd1f9be7290b1
Expand Down
14 changes: 10 additions & 4 deletions branches/beta/pkg/nnbd_migration/lib/src/edge_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
/// For convenience, a [DecoratedType] representing `Null`.
final DecoratedType _nullType;

/// For convenience, a [DecoratedType] representing `dynamic`.
final DecoratedType _dynamicType;

/// The [DecoratedType] of the innermost function or method being visited, or
/// `null` if the visitor is not inside any function or method.
///
Expand Down Expand Up @@ -175,7 +178,8 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
DecoratedType(_typeProvider.boolType, _graph.never),
_nonNullableTypeType =
DecoratedType(_typeProvider.typeType, _graph.never),
_nullType = DecoratedType(_typeProvider.nullType, _graph.always);
_nullType = DecoratedType(_typeProvider.nullType, _graph.always),
_dynamicType = DecoratedType(_typeProvider.dynamicType, _graph.always);

/// Gets the decorated type of [element] from [_variables], performing any
/// necessary substitutions.
Expand Down Expand Up @@ -852,8 +856,10 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
}
var callee = node.methodName.staticElement;
if (callee == null) {
// TODO(paulberry)
_unimplemented(node, 'Unresolved method name');
// Dynamic dispatch. The return type is `dynamic`.
// TODO(paulberry): would it be better to assume a return type of `Never`
// so that we don't unnecessarily propagate nullabilities everywhere?
return _dynamicType;
}
var calleeType = getOrComputeElementType(callee, targetType: targetType);
if (callee is PropertyAccessorElement) {
Expand Down Expand Up @@ -1450,7 +1456,7 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
'(${expression.toSource()}) offset=${expression.offset}');
}
ExpressionChecks expressionChecks;
if (canInsertChecks) {
if (canInsertChecks && !sourceType.type.isDynamic) {
expressionChecks = ExpressionChecks(expression.end);
_variables.recordExpressionChecks(source, expression, expressionChecks);
}
Expand Down
36 changes: 36 additions & 0 deletions branches/beta/pkg/nnbd_migration/test/api_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,42 @@ int f(int i) {
await _checkSingleFileChanges(content, expected);
}

test_dynamic_method_call() async {
var content = '''
class C {
int g(int i) => i;
}
int f(bool b, dynamic d) {
if (b) return 0;
return d.g(null);
}
main() {
f(true, null);
f(false, C());
}
''';
// `d.g(null)` is a dynamic call, so we can't tell that it will target `C.g`
// at runtime. So we can't figure out that we need to make g's argument and
// return types nullable.
//
// We do, however, make f's return type nullable, since there is no way of
// knowing whether a dynamic call will return `null`.
var expected = '''
class C {
int g(int i) => i;
}
int? f(bool b, dynamic d) {
if (b) return 0;
return d.g(null);
}
main() {
f(true, null);
f(false, C());
}
''';
await _checkSingleFileChanges(content, expected);
}

test_field_formal_param_typed() async {
var content = '''
class C {
Expand Down
33 changes: 33 additions & 0 deletions branches/beta/pkg/nnbd_migration/test/edge_builder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,20 @@ class C<T extends List<int>> {
hard: false);
}

test_assign_dynamic_to_other_type() async {
await analyze('''
int f(dynamic d) => d;
''');
// There is no explicit null check necessary, since `dynamic` is
// downcastable to any type, nullable or not.
expect(checkExpression('d;'), isNull);
// But we still create an edge, to make sure that the possibility of `null`
// propagates to callees.
assertEdge(decoratedTypeAnnotation('dynamic').node,
decoratedTypeAnnotation('int').node,
hard: true);
}

test_assign_null_to_generic_type() async {
await analyze('''
main() {
Expand Down Expand Up @@ -2204,6 +2218,25 @@ class C {
assertEdge(decoratedTypeAnnotation('int k').node, never, hard: true);
}

test_methodInvocation_dynamic() async {
await analyze('''
class C {
int g(int i) => i;
}
int f(dynamic d, int j) {
return d.g(j);
}
''');
// The call `d.g(j)` is dynamic, so we can't tell what method it resolves
// to. There's no reason to assume it resolves to `C.g`.
assertNoEdge(decoratedTypeAnnotation('int j').node,
decoratedTypeAnnotation('int i').node);
assertNoEdge(decoratedTypeAnnotation('int g').node,
decoratedTypeAnnotation('int f').node);
// We do, however, assume that it might return anything, including `null`.
assertEdge(always, decoratedTypeAnnotation('int f').node, hard: false);
}

test_methodInvocation_parameter_contravariant() async {
await analyze('''
class C<T> {
Expand Down

0 comments on commit 1e3c17e

Please sign in to comment.