| Index: pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| index b3ec3eb61a30dffadb3b6a2dc1be868cfc9ee549..8d9f708493ed2b2e974e86ca185e152cc8a40378 100644
|
| --- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| +++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| @@ -981,8 +981,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| */
|
| @override
|
| Object visitNullLiteral(NullLiteral node) {
|
| - // TODO(jmesserly): in strong mode, should we just use the context type?
|
| - _recordStaticType(node, _typeProvider.bottomType);
|
| + _recordStaticType(node, _typeProvider.nullType);
|
| return null;
|
| }
|
|
|
| @@ -2079,7 +2078,8 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| // * ExpressionFunctionBody, when the surrounding context had a better type.
|
| // * BlockFunctionBody, if we inferred a type from yield/return.
|
| // * we also normalize bottom to dynamic here.
|
| - if (_strongMode && (computedType.isBottom || computedType.isDynamic)) {
|
| + if (_strongMode &&
|
| + (computedType.isDartCoreNull || computedType.isDynamic)) {
|
| DartType contextType = InferenceContext.getContext(body);
|
| if (contextType is FutureUnionType) {
|
| // TODO(jmesserly): can we do something better here?
|
| @@ -2107,14 +2107,17 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| */
|
| void _inferLocalVariableType(
|
| VariableDeclaration node, Expression initializer) {
|
| - if (initializer != null &&
|
| - (node.parent as VariableDeclarationList).type == null &&
|
| - (resolutionMap.staticTypeForExpression(initializer) != null) &&
|
| - (!resolutionMap.staticTypeForExpression(initializer).isBottom)) {
|
| - VariableElement element = node.element;
|
| - if (element is LocalVariableElementImpl) {
|
| - element.type = initializer.staticType;
|
| - node.name.staticType = initializer.staticType;
|
| + if (initializer != null) {
|
| + AstNode parent = node.parent;
|
| + if (parent is VariableDeclarationList && parent.type == null) {
|
| + DartType type = resolutionMap.staticTypeForExpression(initializer);
|
| + if (type != null && !type.isBottom && !type.isDartCoreNull) {
|
| + VariableElement element = node.element;
|
| + if (element is LocalVariableElementImpl) {
|
| + element.type = initializer.staticType;
|
| + node.name.staticType = initializer.staticType;
|
| + }
|
| + }
|
| }
|
| }
|
| }
|
| @@ -2269,7 +2272,11 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| * @param type the propagated type of the node
|
| */
|
| void _recordPropagatedType(Expression expression, DartType type) {
|
| - if (!_strongMode && type != null && !type.isDynamic && !type.isBottom) {
|
| + if (!_strongMode &&
|
| + type != null &&
|
| + !type.isBottom &&
|
| + !type.isDynamic &&
|
| + !type.isDartCoreNull) {
|
| expression.propagatedType = type;
|
| }
|
| }
|
| @@ -2293,8 +2300,8 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| if (propagatedReturnType == null) {
|
| return;
|
| }
|
| - // Ignore 'bottom' type.
|
| - if (propagatedReturnType.isBottom) {
|
| + // Ignore 'Bottom' and 'Null' types.
|
| + if (propagatedReturnType.isBottom || propagatedReturnType.isDartCoreNull) {
|
| return;
|
| }
|
| // Record only if we inferred more specific type.
|
| @@ -2410,7 +2417,7 @@ class _StaticTypeAnalyzer_computePropagatedReturnTypeOfFunction
|
| if (expression != null) {
|
| type = expression.bestType;
|
| } else {
|
| - type = BottomTypeImpl.instance;
|
| + type = _typeProvider.nullType;
|
| }
|
| // merge types
|
| if (result == null) {
|
|
|