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 b7d45f75057990c42574d50559467fe5960a407b..fafb7b9c9fae82ca2a3c71923da080b006e36fc6 100644 |
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
@@ -623,46 +623,45 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
return null; |
} |
+ DartType listDynamicType = |
+ _typeProvider.listType.instantiate(<DartType>[_dynamicType]); |
+ |
// If there are no type arguments and we are in strong mode, try to infer |
// some arguments. |
if (_strongMode) { |
DartType contextType = InferenceContext.getType(node); |
- // If we have a type from the context, use it. |
- if (contextType is InterfaceType && |
- contextType.typeArguments.length == 1 && |
- contextType.element == _typeProvider.listType.element) { |
- _resolver.inferenceContext.recordInference(node, contextType); |
- _recordStaticType(node, contextType); |
- return null; |
- } |
+ // Use both downwards and upwards information to infer the type. |
+ var ts = _typeSystem as StrongTypeSystemImpl; |
+ var elementTypes = node.elements |
+ .map((e) => e.staticType) |
+ .where((t) => t != null) |
+ .toList(); |
+ var listTypeParam = _typeProvider.listType.typeParameters[0].type; |
- // If we don't have a type from the context, try to infer from the |
- // elements |
- if (node.elements.isNotEmpty) { |
- // Infer the list type from the arguments. |
- Iterable<DartType> types = |
- node.elements.map((e) => e.staticType).where((t) => t != null); |
- if (types.isEmpty) { |
- return null; |
- } |
- DartType staticType = types.reduce(_leastUpperBound); |
- if (staticType.isBottom) { |
- staticType = _dynamicType; |
- } |
- DartType listLiteralType = |
- _typeProvider.listType.instantiate(<DartType>[staticType]); |
- if (!staticType.isDynamic) { |
- _resolver.inferenceContext.recordInference(node, listLiteralType); |
- } |
- _recordStaticType(node, listLiteralType); |
+ DartType inferred = ts.inferGenericFunctionCall( |
+ _typeProvider, |
+ _typeProvider.listType, |
+ new List.filled(elementTypes.length, listTypeParam), |
+ elementTypes, |
+ _typeProvider.listType, |
+ contextType, |
+ errorReporter: _resolver.errorReporter, |
+ errorNode: node); |
+ |
+ if (inferred != listDynamicType) { |
+ // TODO(jmesserly): this results in an "inferred" message even when we |
+ // in fact had an error above, because it will still attempt to return |
+ // a type. Perhaps we should record inference from TypeSystem if |
+ // everything was successful? |
+ _resolver.inferenceContext.recordInference(node, inferred); |
+ _recordStaticType(node, inferred); |
return null; |
} |
} |
// If we have no type arguments and couldn't infer any, use dynamic. |
- _recordStaticType( |
- node, _typeProvider.listType.instantiate(<DartType>[_dynamicType])); |
+ _recordStaticType(node, listDynamicType); |
return null; |
} |
@@ -682,6 +681,9 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
Object visitMapLiteral(MapLiteral node) { |
TypeArgumentList typeArguments = node.typeArguments; |
+ DartType mapDynamicType = _typeProvider.mapType |
+ .instantiate(<DartType>[_dynamicType, _dynamicType]); |
+ |
// If we have type arguments, use them |
if (typeArguments != null) { |
DartType staticKeyType = _dynamicType; |
@@ -710,43 +712,40 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
// then try to infer type arguments. |
if (_strongMode) { |
DartType contextType = InferenceContext.getType(node); |
- // If we have a context type, use that for inference. |
- if (contextType is InterfaceType && |
- contextType.typeArguments.length == 2 && |
- contextType.element == _typeProvider.mapType.element) { |
- _resolver.inferenceContext.recordInference(node, contextType); |
- _recordStaticType(node, contextType); |
- return null; |
- } |
- // Otherwise, try to infer a type from the keys and values. |
- if (node.entries.isNotEmpty) { |
- DartType staticKeyType = |
- node.entries.map((e) => e.key.staticType).reduce(_leastUpperBound); |
- DartType staticValueType = node.entries |
- .map((e) => e.value.staticType) |
- .reduce(_leastUpperBound); |
- if (staticKeyType.isBottom) { |
- staticKeyType = _dynamicType; |
- } |
- if (staticValueType.isBottom) { |
- staticValueType = _dynamicType; |
- } |
- DartType mapLiteralType = _typeProvider.mapType |
- .instantiate(<DartType>[staticKeyType, staticValueType]); |
- if (!(staticValueType.isDynamic && staticKeyType.isDynamic)) { |
- _resolver.inferenceContext.recordInference(node, mapLiteralType); |
- } |
- _recordStaticType(node, mapLiteralType); |
+ // Use both downwards and upwards information to infer the type. |
+ var ts = _typeSystem as StrongTypeSystemImpl; |
+ var keyTypes = |
+ node.entries.map((e) => e.key.staticType).where((t) => t != null); |
+ var valueTypes = |
+ node.entries.map((e) => e.value.staticType).where((t) => t != null); |
+ var keyTypeParam = _typeProvider.mapType.typeParameters[0].type; |
+ var valueTypeParam = _typeProvider.mapType.typeParameters[1].type; |
+ |
+ DartType inferred = ts.inferGenericFunctionCall( |
+ _typeProvider, |
+ _typeProvider.mapType, |
+ new List.filled(keyTypes.length, keyTypeParam, growable: true) |
+ ..addAll(new List.filled(valueTypes.length, valueTypeParam)), |
+ new List.from(keyTypes)..addAll(valueTypes), |
+ _typeProvider.mapType, |
+ contextType, |
+ errorReporter: _resolver.errorReporter, |
+ errorNode: node); |
+ |
+ if (inferred != mapDynamicType) { |
+ // TODO(jmesserly): this results in an "inferred" message even when we |
+ // in fact had an error above, because it will still attempt to return |
+ // a type. Perhaps we should record inference from TypeSystem if |
+ // everything was successful? |
+ _resolver.inferenceContext.recordInference(node, inferred); |
+ _recordStaticType(node, inferred); |
return null; |
} |
} |
// If no type arguments and no inference, use dynamic |
- _recordStaticType( |
- node, |
- _typeProvider.mapType |
- .instantiate(<DartType>[_dynamicType, _dynamicType])); |
+ _recordStaticType(node, mapDynamicType); |
return null; |
} |
@@ -1986,7 +1985,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
} |
} |
return ts.inferGenericFunctionCall(_typeProvider, fnType, paramTypes, |
- argTypes, InferenceContext.getContext(node), |
+ argTypes, fnType.returnType, InferenceContext.getContext(node), |
errorReporter: _resolver.errorReporter, errorNode: errorNode); |
} |
return null; |
@@ -2251,14 +2250,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
} |
/** |
- * Computes the least upper bound between two types. |
- * |
- * See [TypeSystem.getLeastUpperBound]. |
- */ |
- DartType _leastUpperBound(DartType s, DartType t) => |
- _typeSystem.getLeastUpperBound(_typeProvider, s, t); |
- |
- /** |
* Record that the propagated type of the given node is the given type. |
* |
* @param expression the node whose type is to be recorded |