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

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

Issue 2456803004: fixes #27586, prefer context type in generic inference (Closed)
Patch Set: fix Created 3 years, 9 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 4b96f41e8d0d841b4df240ef960c82290204eef4..52a7eafefd0e0d73f0dad121642c0a355aba73a2 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -106,9 +106,10 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
void inferConstructorName(ConstructorName node, InterfaceType type) {
if (_strongMode) {
node.type.type = type;
- _resolver.inferenceContext.recordInference(node.parent, type);
+ if (type != _typeSystem.instantiateToBounds(type.element.type)) {
+ _resolver.inferenceContext.recordInference(node.parent, type);
+ }
}
- return;
}
/**
@@ -121,14 +122,17 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
FormalParameterList node, DartType functionType) {
bool inferred = false;
if (_strongMode && node != null && functionType is FunctionType) {
+ var ts = _typeSystem as StrongTypeSystemImpl;
void inferType(ParameterElementImpl p, DartType inferredType) {
// Check that there is no declared type, and that we have not already
// inferred a type in some fashion.
if (p.hasImplicitType &&
- (p.type == null || p.type.isDynamic) &&
- !inferredType.isDynamic) {
- p.type = inferredType;
- inferred = true;
+ (p.type == null || p.type.isDynamic)) {
+ inferredType = ts.upperBoundForType(inferredType);
+ if (!inferredType.isDynamic) {
+ p.type = inferredType;
+ inferred = true;
+ }
}
}
@@ -628,24 +632,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
// If there are no type arguments and we are in strong mode, try to infer
// some arguments.
if (_strongMode) {
- DartType contextType = InferenceContext.getType(node);
-
- // 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;
-
- DartType inferred = ts.inferGenericFunctionCall(
- _typeProvider.listType,
- new List.filled(elementTypes.length, listTypeParam),
- elementTypes,
- _typeProvider.listType,
- contextType,
- errorReporter: _resolver.errorReporter,
- errorNode: node);
+ DartType inferred = inferListType(node);
if (inferred != listDynamicType) {
// TODO(jmesserly): this results in an "inferred" message even when we
@@ -663,6 +650,39 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
return null;
}
+ DartType inferListType(ListLiteral node, {bool downwards: false}) {
+ DartType contextType = InferenceContext.getContext(node);
+
+ var ts = _typeSystem as StrongTypeSystemImpl;
+ List<DartType> elementTypes;
+ List<ParameterElement> parameters;
+
+ if (downwards) {
+ if (contextType == null) {
+ return null;
+ }
+
+ elementTypes = [];
+ parameters = [];
+ } else {
+ // Also use upwards information to infer the type.
+ elementTypes = node.elements
+ .map((e) => e.staticType)
+ .where((t) => t != null)
+ .toList();
+ var listTypeParam = _typeProvider.listType.typeParameters[0].type;
+ var syntheticParamElement = new ParameterElementImpl.synthetic(
+ 'element', listTypeParam, ParameterKind.POSITIONAL);
+ parameters = new List.filled(elementTypes.length, syntheticParamElement);
+ }
+ DartType inferred = ts.inferGenericFunctionOrType/*<InterfaceType>*/(
+ _typeProvider.listType, parameters, elementTypes, contextType,
+ downwards: downwards,
+ errorReporter: _resolver.errorReporter,
+ errorNode: node);
+ return inferred;
+ }
+
/**
* The Dart Language Specification, 12.7: <blockquote>The static type of a map literal of the form
* <i><b>const</b> &lt;K, V&gt; {k<sub>1</sub>:e<sub>1</sub>, &hellip;,
@@ -707,26 +727,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
// If we have no explicit type arguments, and we are in strong mode
// then try to infer type arguments.
if (_strongMode) {
- DartType contextType = InferenceContext.getType(node);
-
- // 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.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);
+ ParameterizedType inferred = inferMapType(node);
if (inferred != mapDynamicType) {
// TODO(jmesserly): this results in an "inferred" message even when we
@@ -744,6 +745,42 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
return null;
}
+ ParameterizedType inferMapType(MapLiteral node, {bool downwards: false}) {
+ DartType contextType = InferenceContext.getContext(node);
+
+ List<DartType> elementTypes;
+ List<ParameterElement> parameters;
+ if (downwards) {
+ if (contextType == null) {
+ return null;
+ }
+ elementTypes = [];
+ parameters = [];
+ } else {
+ 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;
+ var syntheticKeyParameter = new ParameterElementImpl.synthetic(
+ 'key', keyTypeParam, ParameterKind.POSITIONAL);
+ var syntheticValueParameter = new ParameterElementImpl.synthetic(
+ 'value', valueTypeParam, ParameterKind.POSITIONAL);
+ parameters = new List.filled(keyTypes.length, syntheticKeyParameter,
+ growable: true)
+ ..addAll(new List.filled(valueTypes.length, syntheticValueParameter));
+ elementTypes = new List<DartType>.from(keyTypes)..addAll(valueTypes);
+ }
+
+ // Use both downwards and upwards information to infer the type.
+ var ts = _typeSystem as StrongTypeSystemImpl;
+ ParameterizedType inferred = ts.inferGenericFunctionOrType(
+ _typeProvider.mapType, parameters, elementTypes, contextType,
+ errorReporter: _resolver.errorReporter, errorNode: node);
+ return inferred;
+ }
+
/**
* The Dart Language Specification, 12.15.1: <blockquote>An ordinary method invocation <i>i</i>
* has the form <i>o.m(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>,
@@ -1073,7 +1110,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
staticType = staticElement.type;
}
staticType = _inferGenericInstantiationFromContext(node, staticType);
-
if (!(_strongMode &&
_inferObjectAccess(node, staticType, prefixedIdentifier))) {
_recordStaticType(prefixedIdentifier, staticType);
@@ -1204,7 +1240,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
// TODO(brianwilkerson) Report this internal error.
}
staticType = _inferGenericInstantiationFromContext(node, staticType);
-
if (!(_strongMode && _inferObjectAccess(node, staticType, propertyName))) {
_recordStaticType(propertyName, staticType);
_recordStaticType(node, staticType);
@@ -1306,7 +1341,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
staticType = _dynamicType;
}
staticType = _inferGenericInstantiationFromContext(node, staticType);
-
_recordStaticType(node, staticType);
// TODO(brianwilkerson) I think we want to repeat the logic above using the
// propagated element to get another candidate for the propagated type.
@@ -1620,7 +1654,11 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
type = type.substitute2(freshTypeVars, typeVars);
- var function = new FunctionElementImpl("", -1);
+ var name = cls.name;
+ if (constructor.name != null) {
+ name += '.' + constructor.name;
+ }
+ var function = new FunctionElementImpl(name, -1);
function.enclosingElement = cls;
function.isSynthetic = true;
function.returnType = type.returnType;
@@ -1903,11 +1941,12 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
DartType _inferGenericInstantiationFromContext(AstNode node, DartType type) {
if (_strongMode) {
TypeSystem ts = _typeSystem;
- DartType context = InferenceContext.getType(node);
+ var context = InferenceContext.getContext(node);
if (context is FunctionType &&
type is FunctionType &&
ts is StrongTypeSystemImpl) {
- return ts.inferFunctionTypeInstantiation(context, type);
+ return ts.inferFunctionTypeInstantiation(context, type,
+ errorReporter: _resolver.errorReporter, errorNode: node);
}
} else if (type is FunctionType) {
// In Dart 1 mode we want to implicitly instantiate generic functions to
@@ -1959,12 +1998,12 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
List<ParameterElement> rawParameters = ResolverVisitor
.resolveArgumentsToParameters(argumentList, fnType.parameters, null);
- List<DartType> paramTypes = <DartType>[];
+ List<ParameterElement> params = <ParameterElement>[];
List<DartType> argTypes = <DartType>[];
for (int i = 0, length = rawParameters.length; i < length; i++) {
ParameterElement parameter = rawParameters[i];
if (parameter != null) {
- paramTypes.add(parameter.type);
+ params.add(parameter);
argTypes.add(argumentList.arguments[i].staticType);
}
}
@@ -1983,7 +2022,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
// ... and finish the inference using that.
if (argTypes.isNotEmpty && _resolver.isFutureThen(fnType.element)) {
var firstArgType = argTypes[0];
- var firstParamType = paramTypes[0];
+ var firstParamType = params[0].type;
if (firstArgType is FunctionType &&
firstParamType is FunctionType &&
!firstParamType.returnType.isDartAsyncFutureOr) {
@@ -1998,17 +2037,18 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
// Adjust the expected parameter type to have this return type.
var function = new FunctionElementImpl(firstParamType.name, -1)
..isSynthetic = true
- ..shareParameters(firstParamType.parameters)
+ ..shareParameters(firstParamType.parameters.toList())
..returnType = paramReturnType;
function.type = new FunctionTypeImpl(function);
// Use this as the expected 1st parameter type.
- paramTypes[0] = function.type;
+ params[0] = new ParameterElementImpl.synthetic(
+ params[0].name, function.type, params[0].parameterKind);
}
}
}
- return ts.inferGenericFunctionCall(fnType, paramTypes, argTypes,
- fnType.returnType, InferenceContext.getContext(node),
+ return ts.inferGenericFunctionOrType(
+ fnType, params, argTypes, InferenceContext.getContext(node),
errorReporter: _resolver.errorReporter, errorNode: errorNode);
}
return null;
@@ -2043,8 +2083,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
// Or look it up, instead of jumping backwards through the Member?
var rawElement = (originalElement as ConstructorMember).baseElement;
- FunctionType constructorType =
- constructorToGenericFunctionType(rawElement);
+ FunctionType constructorType = constructorToGenericFunctionType(rawElement);
ArgumentList arguments = node.argumentList;
FunctionType inferred = _inferGenericInvoke(node, constructorType,
« no previous file with comments | « pkg/analyzer/lib/src/generated/resolver.dart ('k') | pkg/analyzer/lib/src/generated/testing/test_type_provider.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698