Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(451)

Unified Diff: pkg/analyzer/lib/src/generated/static_type_analyzer.dart

Issue 2343713002: fix #27151, list and map literals infer using up and down info (Closed)
Patch Set: format Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698