Skip to content

Commit 88dbb00

Browse files
author
John Messerly
committed
fixes inferring () -> <bottom> in strong mode
This fixes dart-archive/dev_compiler#47 [email protected] Review URL: https://codereview.chromium.org/1649523002 .
1 parent 33aaf94 commit 88dbb00

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

pkg/analyzer/lib/src/generated/static_type_analyzer.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,19 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
466466
node.element as ExecutableElementImpl;
467467
DartType computedType = _computeStaticReturnTypeOfFunctionExpression(node);
468468
if (_strongMode) {
469+
// In strong mode, we don't want to allow the function's return type to
470+
// be bottom. If the surrounding context has a more precise type, we
471+
// will push it down with inference, below. If not we want to use dynamic.
472+
// TODO(jmesserly): should we do this for the `null` literal always in
473+
// strong mode, instead of handling it here?
474+
if (computedType.isBottom) {
475+
computedType = DynamicTypeImpl.instance;
476+
}
477+
469478
DartType functionType = InferenceContext.getType(node);
470479
if (functionType is FunctionType) {
471480
DartType returnType = functionType.returnType;
472-
if ((computedType.isDynamic || computedType.isBottom) &&
481+
if (computedType.isDynamic &&
473482
!(returnType.isDynamic || returnType.isBottom)) {
474483
computedType = returnType;
475484
_resolver.inferenceContext.recordInference(node, functionType);

pkg/analyzer/test/src/task/strong/inferred_type_test.dart

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,10 +1584,32 @@ main() {
15841584
'''
15851585
});
15861586

1587+
// Regression test for https://github.com/dart-lang/dev_compiler/issues/47
1588+
testChecker('null literal should not infer as bottom', {
1589+
'/main.dart': '''
1590+
var h = null;
1591+
void foo(int f(Object _)) {}
1592+
1593+
main() {
1594+
var f = (x) => null;
1595+
f = (x) => 'hello';
1596+
1597+
var g = null;
1598+
g = 'hello';
1599+
(/*info:DYNAMIC_INVOKE*/g.foo());
1600+
1601+
h = 'hello';
1602+
(/*info:DYNAMIC_INVOKE*/h.foo());
1603+
1604+
foo(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) => null);
1605+
foo(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) => throw "not implemented");
1606+
}
1607+
'''
1608+
});
1609+
15871610
// TODO(jmesserly): we should change how this inference works.
15881611
// For now this test will cover what we use.
1589-
testChecker(
1590-
'infer from RHS only if it wont conflict with overridden fields 2', {
1612+
testChecker('infer JS builtin', {
15911613
'/main.dart': '''
15921614
import 'dart:_foreign_helper' show JS;
15931615
main() {
@@ -1598,6 +1620,5 @@ main() {
15981620
}
15991621
'''
16001622
});
1601-
16021623
});
16031624
}

0 commit comments

Comments
 (0)