Index: pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart |
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart |
index f51ba659ba6d2a52f6cb2b01ac588e897e9452d4..8b56013254df04d8b1776370edcafc7e7e46c82d 100644 |
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart |
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart |
@@ -231,6 +231,8 @@ abstract class TypeInferrerImpl extends TypeInferrer { |
/// Not used when performing local inference. |
bool isImmediatelyEvident = true; |
+ List<FieldNode> _dryRunDependencies; |
+ |
TypeInferrerImpl(TypeInferenceEngineImpl engine, this.uri, this.listener, |
bool topLevel, this.thisType) |
: coreTypes = engine.coreTypes, |
@@ -240,6 +242,10 @@ abstract class TypeInferrerImpl extends TypeInferrer { |
typeSchemaEnvironment = engine.typeSchemaEnvironment, |
isTopLevel = topLevel; |
+ /// Indicates whether we are currently doing a "dry run" in order to collect |
+ /// type inference dependencies. |
+ bool get isDryRun => _dryRunDependencies != null; |
+ |
/// Gets the type promoter that should be used to promote types during |
/// inference. |
TypePromoter get typePromoter; |
@@ -336,6 +342,14 @@ abstract class TypeInferrerImpl extends TypeInferrer { |
} |
} |
+ /// Ends a dry run started by [startDryRun] and returns the collected |
+ /// dependencies. |
+ List<FieldNode> finishDryRun() { |
+ var dryRunDependencies = _dryRunDependencies; |
+ _dryRunDependencies = null; |
+ return dryRunDependencies; |
+ } |
+ |
FunctionType getCalleeFunctionType(Member interfaceMember, |
DartType receiverType, Name methodName, bool followCall) { |
var type = getCalleeType(interfaceMember, receiverType, methodName); |
@@ -517,7 +531,8 @@ abstract class TypeInferrerImpl extends TypeInferrer { |
FunctionType calleeType, DartType returnType, Arguments arguments, |
{bool isOverloadedArithmeticOperator: false, |
DartType receiverType, |
- bool skipTypeArgumentInference: false}) { |
+ bool skipTypeArgumentInference: false, |
+ bool forceArgumentInference: false}) { |
var calleeTypeParameters = calleeType.typeParameters; |
List<DartType> explicitTypeArguments = getExplicitTypeArguments(arguments); |
bool inferenceNeeded = !skipTypeArgumentInference && |
@@ -558,8 +573,12 @@ abstract class TypeInferrerImpl extends TypeInferrer { |
DartType inferredFormalType = substitution != null |
? substitution.substituteType(formalType) |
: formalType; |
- var expressionType = inferExpression(expression, inferredFormalType, |
- inferenceNeeded || isOverloadedArithmeticOperator); |
+ var expressionType = inferExpression( |
+ expression, |
+ inferredFormalType, |
+ inferenceNeeded || |
+ isOverloadedArithmeticOperator || |
+ forceArgumentInference); |
if (inferenceNeeded) { |
formalTypes.add(formalType); |
actualTypes.add(expressionType); |
@@ -624,12 +643,28 @@ abstract class TypeInferrerImpl extends TypeInferrer { |
/// the statement type and calls the appropriate specialized "infer" method. |
void inferStatement(Statement statement); |
+ /// Records that the field represented by [fieldNode] is a dependency of the |
+ /// static field for which we are currently doing a dry run of type inference. |
+ /// |
+ /// May only be called if a dry run is in progress. |
+ void recordDryRunDependency(FieldNode fieldNode) { |
+ listener.recordDependency(fieldNode); |
+ _dryRunDependencies.add(fieldNode); |
+ } |
+ |
void recordNotImmediatelyEvident(int fileOffset) { |
assert(isTopLevel); |
isImmediatelyEvident = false; |
// TODO(paulberry): report an error. |
} |
+ /// Begins a dry run of type inference, in which the goal is to collect the |
+ /// dependencies of a given field. |
+ void startDryRun() { |
+ assert(_dryRunDependencies == null); |
+ _dryRunDependencies = <FieldNode>[]; |
+ } |
+ |
DartType wrapFutureOrType(DartType type) { |
if (type is InterfaceType && |
identical(type.classNode, coreTypes.futureOrClass)) { |