Skip to content

Commit 1e3c17e

Browse files
stereotype441commit-bot@chromium.org
authored and
commit-bot@chromium.org
committed
---
yaml --- r: 191340 b: refs/heads/beta c: c604e58 h: refs/heads/master
1 parent fee326e commit 1e3c17e

File tree

4 files changed

+80
-5
lines changed

4 files changed

+80
-5
lines changed

[refs]

+1-1
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,7 @@ refs/tags/2.3.0-flutter-1.5.4-hotfix.1: a1668566e563aef64025d0af88a099cbbe847b7e
911911
refs/tags/2.3.1: 929b013ddc83a013b49a98fc28b6b503a972bddd
912912
refs/tags/2.3.1-dev.0.0: 1d1742efd39cd4762b844b510acf8c2f1fa6604e
913913
refs/tags/2.3.2-dev.0.0: c567183bac8a895014d79cd3bf1d8908d45547d6
914-
refs/heads/beta: c7ac27bf504cca030881208eb0b056a5a7ff93c2
914+
refs/heads/beta: c604e58a9b387856a630391aa0ec88acc010b88e
915915
refs/heads/sjindel.mep: b113b36c157cf54b257e82550e9bbde16f05ad8d
916916
refs/tags/2.3.2: f7ab96133aa79301daf812ef40b33c99d8ad1495
917917
refs/tags/2.3.2-dev.0.1: ef57e27c9798b54a54e9a1f74b1bd1f9be7290b1

branches/beta/pkg/nnbd_migration/lib/src/edge_builder.dart

+10-4
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
124124
/// For convenience, a [DecoratedType] representing `Null`.
125125
final DecoratedType _nullType;
126126

127+
/// For convenience, a [DecoratedType] representing `dynamic`.
128+
final DecoratedType _dynamicType;
129+
127130
/// The [DecoratedType] of the innermost function or method being visited, or
128131
/// `null` if the visitor is not inside any function or method.
129132
///
@@ -175,7 +178,8 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
175178
DecoratedType(_typeProvider.boolType, _graph.never),
176179
_nonNullableTypeType =
177180
DecoratedType(_typeProvider.typeType, _graph.never),
178-
_nullType = DecoratedType(_typeProvider.nullType, _graph.always);
181+
_nullType = DecoratedType(_typeProvider.nullType, _graph.always),
182+
_dynamicType = DecoratedType(_typeProvider.dynamicType, _graph.always);
179183

180184
/// Gets the decorated type of [element] from [_variables], performing any
181185
/// necessary substitutions.
@@ -852,8 +856,10 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
852856
}
853857
var callee = node.methodName.staticElement;
854858
if (callee == null) {
855-
// TODO(paulberry)
856-
_unimplemented(node, 'Unresolved method name');
859+
// Dynamic dispatch. The return type is `dynamic`.
860+
// TODO(paulberry): would it be better to assume a return type of `Never`
861+
// so that we don't unnecessarily propagate nullabilities everywhere?
862+
return _dynamicType;
857863
}
858864
var calleeType = getOrComputeElementType(callee, targetType: targetType);
859865
if (callee is PropertyAccessorElement) {
@@ -1450,7 +1456,7 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
14501456
'(${expression.toSource()}) offset=${expression.offset}');
14511457
}
14521458
ExpressionChecks expressionChecks;
1453-
if (canInsertChecks) {
1459+
if (canInsertChecks && !sourceType.type.isDynamic) {
14541460
expressionChecks = ExpressionChecks(expression.end);
14551461
_variables.recordExpressionChecks(source, expression, expressionChecks);
14561462
}

branches/beta/pkg/nnbd_migration/test/api_test.dart

+36
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,42 @@ int f(int i) {
821821
await _checkSingleFileChanges(content, expected);
822822
}
823823

824+
test_dynamic_method_call() async {
825+
var content = '''
826+
class C {
827+
int g(int i) => i;
828+
}
829+
int f(bool b, dynamic d) {
830+
if (b) return 0;
831+
return d.g(null);
832+
}
833+
main() {
834+
f(true, null);
835+
f(false, C());
836+
}
837+
''';
838+
// `d.g(null)` is a dynamic call, so we can't tell that it will target `C.g`
839+
// at runtime. So we can't figure out that we need to make g's argument and
840+
// return types nullable.
841+
//
842+
// We do, however, make f's return type nullable, since there is no way of
843+
// knowing whether a dynamic call will return `null`.
844+
var expected = '''
845+
class C {
846+
int g(int i) => i;
847+
}
848+
int? f(bool b, dynamic d) {
849+
if (b) return 0;
850+
return d.g(null);
851+
}
852+
main() {
853+
f(true, null);
854+
f(false, C());
855+
}
856+
''';
857+
await _checkSingleFileChanges(content, expected);
858+
}
859+
824860
test_field_formal_param_typed() async {
825861
var content = '''
826862
class C {

branches/beta/pkg/nnbd_migration/test/edge_builder_test.dart

+33
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,20 @@ class C<T extends List<int>> {
384384
hard: false);
385385
}
386386

387+
test_assign_dynamic_to_other_type() async {
388+
await analyze('''
389+
int f(dynamic d) => d;
390+
''');
391+
// There is no explicit null check necessary, since `dynamic` is
392+
// downcastable to any type, nullable or not.
393+
expect(checkExpression('d;'), isNull);
394+
// But we still create an edge, to make sure that the possibility of `null`
395+
// propagates to callees.
396+
assertEdge(decoratedTypeAnnotation('dynamic').node,
397+
decoratedTypeAnnotation('int').node,
398+
hard: true);
399+
}
400+
387401
test_assign_null_to_generic_type() async {
388402
await analyze('''
389403
main() {
@@ -2204,6 +2218,25 @@ class C {
22042218
assertEdge(decoratedTypeAnnotation('int k').node, never, hard: true);
22052219
}
22062220

2221+
test_methodInvocation_dynamic() async {
2222+
await analyze('''
2223+
class C {
2224+
int g(int i) => i;
2225+
}
2226+
int f(dynamic d, int j) {
2227+
return d.g(j);
2228+
}
2229+
''');
2230+
// The call `d.g(j)` is dynamic, so we can't tell what method it resolves
2231+
// to. There's no reason to assume it resolves to `C.g`.
2232+
assertNoEdge(decoratedTypeAnnotation('int j').node,
2233+
decoratedTypeAnnotation('int i').node);
2234+
assertNoEdge(decoratedTypeAnnotation('int g').node,
2235+
decoratedTypeAnnotation('int f').node);
2236+
// We do, however, assume that it might return anything, including `null`.
2237+
assertEdge(always, decoratedTypeAnnotation('int f').node, hard: false);
2238+
}
2239+
22072240
test_methodInvocation_parameter_contravariant() async {
22082241
await analyze('''
22092242
class C<T> {

0 commit comments

Comments
 (0)