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 b4b6cfad15c09de3576979d2b06865d6f191a9b9..634115741fe67a1f8ab38b7153c16e1330aff7cb 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 |
@@ -4,6 +4,7 @@ |
import 'package:front_end/src/base/instrumentation.dart'; |
import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart'; |
+import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'; |
import 'package:front_end/src/fasta/type_inference/type_promotion.dart'; |
import 'package:front_end/src/fasta/type_inference/type_schema.dart'; |
import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart'; |
@@ -84,11 +85,13 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
final TypeSchemaEnvironment typeSchemaEnvironment; |
+ final TypeInferenceListener listener; |
+ |
/// Context information for the current closure, or `null` if we are not |
/// inside a closure. |
_ClosureContext _closureContext; |
- TypeInferrerImpl(TypeInferenceEngineImpl<F> engine, this.uri) |
+ TypeInferrerImpl(TypeInferenceEngineImpl<F> engine, this.uri, this.listener) |
: coreTypes = engine.coreTypes, |
strongMode = engine.strongMode, |
classHierarchy = engine.classHierarchy, |
@@ -109,8 +112,11 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
/// [inferExpression]. |
DartType inferAsExpression( |
DartType typeContext, bool typeNeeded, E operand, DartType type) { |
+ typeNeeded = listener.asExpressionEnter(typeContext) || typeNeeded; |
inferExpression(operand, null, false); |
Siggi Cherem (dart-lang)
2017/05/12 20:13:14
is eventually the idea that if typeNeeded is false
Paul Berry
2017/05/12 20:22:21
We can't skip the recursive calls (they are needed
|
- return typeNeeded ? type : null; |
+ var inferredType = typeNeeded ? type : null; |
+ listener.asExpressionExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for boolean literals. |
@@ -118,7 +124,10 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
/// [typeContext], [typeNeeded], and the return value behave as described in |
/// [inferExpression]. |
DartType inferBoolLiteral(DartType typeContext, bool typeNeeded) { |
- return typeNeeded ? coreTypes.boolClass.rawType : null; |
+ typeNeeded = listener.boolLiteralEnter(typeContext) || typeNeeded; |
+ var inferredType = typeNeeded ? coreTypes.boolClass.rawType : null; |
+ listener.boolLiteralExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for conditional expressions. |
@@ -130,6 +139,7 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
/// type is reported via [setStaticType]. |
DartType inferConditionalExpression(DartType typeContext, bool typeNeeded, |
E condition, E then, E otherwise, void setStaticType(DartType type)) { |
+ typeNeeded = listener.conditionalExpressionEnter(typeContext) || typeNeeded; |
inferExpression(condition, coreTypes.boolClass.rawType, false); |
// TODO(paulberry): is it correct to pass the context down? |
DartType thenType = inferExpression(then, typeContext, true); |
@@ -140,7 +150,9 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
DartType type = |
typeSchemaEnvironment.getLeastUpperBound(thenType, otherwiseType); |
setStaticType(type); |
- return typeNeeded ? type : null; |
+ var inferredType = typeNeeded ? type : null; |
+ listener.conditionalExpressionExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for constructor invocations. |
@@ -163,6 +175,7 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
List<DartType> explicitTypeArguments, |
void forEachArgument(void callback(String name, E expression)), |
void setInferredTypeArguments(List<DartType> types)) { |
+ typeNeeded = listener.constructorInvocationEnter(typeContext) || typeNeeded; |
List<DartType> inferredTypes; |
FunctionType constructorType = target.function.functionType; |
Substitution substitution; |
@@ -215,13 +228,14 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
new InstrumentationValueForTypeArgs(inferredTypes)); |
setInferredTypeArguments(inferredTypes); |
} |
+ DartType inferredType; |
if (typeNeeded) { |
- return substitution == null |
+ inferredType = substitution == null |
? targetClass.rawType |
: substitution.substituteType(targetClass.thisType); |
- } else { |
- return null; |
} |
+ listener.constructorInvocationExit(inferredType); |
+ return inferredType; |
} |
/// Maps the type of a variable's initializer expression to the correct |
@@ -244,7 +258,10 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
/// [typeContext], [typeNeeded], and the return value behave as described in |
/// [inferExpression]. |
DartType inferDoubleLiteral(DartType typeContext, bool typeNeeded) { |
- return typeNeeded ? coreTypes.doubleClass.rawType : null; |
+ typeNeeded = listener.doubleLiteralEnter(typeContext) || typeNeeded; |
+ var inferredType = typeNeeded ? coreTypes.doubleClass.rawType : null; |
+ listener.doubleLiteralExit(inferredType); |
+ return inferredType; |
} |
/// Performs type inference on the given [expression]. |
@@ -293,6 +310,7 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
int offset, |
void setReturnType(DartType type), |
DartType getFunctionType()) { |
+ typeNeeded = listener.functionExpressionEnter(typeContext) || typeNeeded; |
// TODO(paulberry): do we also need to visit default parameter values? |
// TODO(paulberry): infer argument types and type parameters. |
// TODO(paulberry): full support for generators. |
@@ -317,11 +335,9 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
setReturnType(inferredReturnType); |
} |
_closureContext = oldClosureContext; |
- if (typeNeeded) { |
- return getFunctionType(); |
- } else { |
- return null; |
- } |
+ var inferredType = typeNeeded ? getFunctionType() : null; |
+ listener.functionExpressionExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for if statements. |
@@ -336,7 +352,10 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
/// [typeContext], [typeNeeded], and the return value behave as described in |
/// [inferExpression]. |
DartType inferIntLiteral(DartType typeContext, bool typeNeeded) { |
- return typeNeeded ? coreTypes.intClass.rawType : null; |
+ typeNeeded = listener.intLiteralEnter(typeContext) || typeNeeded; |
+ var inferredType = typeNeeded ? coreTypes.intClass.rawType : null; |
+ listener.intLiteralExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for an "is" expression. |
@@ -346,8 +365,11 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
/// |
/// [operand] is the expression appearing to the left of "is". |
DartType inferIsExpression(DartType typeContext, bool typeNeeded, E operand) { |
+ typeNeeded = listener.isExpressionEnter(typeContext) || typeNeeded; |
inferExpression(operand, null, false); |
- return typeNeeded ? coreTypes.boolClass.rawType : null; |
+ var inferredType = typeNeeded ? coreTypes.boolClass.rawType : null; |
+ listener.isExpressionExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for list literals. |
@@ -361,6 +383,7 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
DartType declaredTypeArgument, |
Iterable<E> expressions, |
void setTypeArgument(DartType typeArgument)) { |
+ typeNeeded = listener.listLiteralEnter(typeContext) || typeNeeded; |
var listClass = coreTypes.listClass; |
var listType = listClass.thisType; |
List<DartType> inferredTypes; |
@@ -399,9 +422,11 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
new InstrumentationValueForTypeArgs([inferredTypeArgument])); |
setTypeArgument(inferredTypeArgument); |
} |
- return typeNeeded |
+ var inferredType = typeNeeded |
? new InterfaceType(listClass, [inferredTypeArgument]) |
: null; |
+ listener.listLiteralExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for method invocations. |
@@ -428,6 +453,7 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
void forEachArgument(void callback(String name, E expression)), |
void setInferredTypeArguments(List<DartType> types), |
void setInterfaceTarget(Procedure procedure)) { |
+ typeNeeded = listener.methodInvocationEnter(typeContext) || typeNeeded; |
// First infer the receiver so we can look up the method that was invoked. |
var receiverType = inferExpression(receiver, null, true); |
// TODO(paulberry): can we share some of the code below with |
@@ -491,13 +517,14 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
new InstrumentationValueForTypeArgs(inferredTypes)); |
setInferredTypeArguments(inferredTypes); |
} |
+ DartType inferredType; |
if (typeNeeded) { |
- return substitution == null |
+ inferredType = substitution == null |
? memberFunctionType.returnType |
: substitution.substituteType(memberFunctionType.returnType); |
- } else { |
- return null; |
} |
+ listener.methodInvocationExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for null literals. |
@@ -505,7 +532,10 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
/// [typeContext], [typeNeeded], and the return value behave as described in |
/// [inferExpression]. |
DartType inferNullLiteral(DartType typeContext, bool typeNeeded) { |
- return typeNeeded ? coreTypes.nullClass.rawType : null; |
+ typeNeeded = listener.nullLiteralEnter(typeContext) || typeNeeded; |
+ var inferredType = typeNeeded ? coreTypes.nullClass.rawType : null; |
+ listener.nullLiteralExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for static variable getters. |
@@ -517,7 +547,10 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
/// of the getter. |
DartType inferStaticGet( |
DartType typeContext, bool typeNeeded, DartType getterType) { |
- return typeNeeded ? getterType : null; |
+ typeNeeded = listener.staticGetEnter(typeContext) || typeNeeded; |
+ var inferredType = typeNeeded ? getterType : null; |
+ listener.staticGetExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for string concatenations. |
@@ -526,10 +559,13 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
/// [inferExpression]. |
DartType inferStringConcatenation( |
DartType typeContext, bool typeNeeded, Iterable<E> expressions) { |
+ typeNeeded = listener.stringConcatenationEnter(typeContext) || typeNeeded; |
for (E expression in expressions) { |
inferExpression(expression, null, false); |
} |
- return typeNeeded ? coreTypes.stringClass.rawType : null; |
+ var inferredType = typeNeeded ? coreTypes.stringClass.rawType : null; |
+ listener.stringConcatenationExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for string literals. |
@@ -537,7 +573,10 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
/// [typeContext], [typeNeeded], and the return value behave as described in |
/// [inferExpression]. |
DartType inferStringLiteral(DartType typeContext, bool typeNeeded) { |
- return typeNeeded ? coreTypes.stringClass.rawType : null; |
+ typeNeeded = listener.stringLiteralEnter(typeContext) || typeNeeded; |
+ var inferredType = typeNeeded ? coreTypes.stringClass.rawType : null; |
+ listener.stringLiteralExit(inferredType); |
+ return inferredType; |
} |
/// Performs the core type inference algorithm for variable declarations. |
@@ -568,6 +607,7 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
int offset, |
DartType declaredOrInferredType, |
void setPromotedType(DartType type)) { |
+ typeNeeded = listener.variableGetEnter(typeContext) || typeNeeded; |
DartType promotedType = typePromoter.computePromotedType( |
typePromotionFact, typePromotionScope, mutatedInClosure); |
if (promotedType != null) { |
@@ -575,12 +615,18 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> { |
new InstrumentationValueForType(promotedType)); |
} |
setPromotedType(promotedType); |
- return typeNeeded ? (promotedType ?? declaredOrInferredType) : null; |
+ var inferredType = |
+ typeNeeded ? (promotedType ?? declaredOrInferredType) : null; |
+ listener.variableGetExit(inferredType); |
+ return inferredType; |
} |
DartType inferVariableSet( |
DartType typeContext, bool typeNeeded, DartType declaredType, E value) { |
- return inferExpression(value, declaredType, typeNeeded); |
+ typeNeeded = listener.variableSetEnter(typeContext) || typeNeeded; |
+ var inferredType = inferExpression(value, declaredType, typeNeeded); |
+ listener.variableSetExit(inferredType); |
+ return inferredType; |
} |
FunctionType _getCalleeFunctionType(DartType receiverType, Name methodName, |