| 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)) {
|
|
|