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

Unified Diff: pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart

Issue 2865623003: Implement type inference of constructor invocations in Fasta. (Closed)
Patch Set: Created 3 years, 7 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/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 343872c577705469ef4b9a4e3987e58b98dd209d..b6b11317291f7bb6ce18d4edc8e26a9c9e3991ec 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
@@ -7,8 +7,16 @@ import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
import 'package:front_end/src/fasta/type_inference/type_promotion.dart';
import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
import 'package:kernel/ast.dart'
- show BottomType, DartType, DynamicType, InterfaceType, Member;
+ show
+ BottomType,
+ Constructor,
+ DartType,
+ DynamicType,
+ FunctionNode,
+ InterfaceType,
+ Member;
import 'package:kernel/core_types.dart';
+import 'package:kernel/type_algebra.dart';
/// Keeps track of the local state for the type inference that occurs during
/// compilation of a single method body or top level initializer.
@@ -122,6 +130,81 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> {
return typeNeeded ? type : null;
}
+ /// Performs the core type inference algorithm for constructor invocations.
+ ///
+ /// [typeContext], [typeNeeded], and the return value behave as described in
+ /// [inferExpression].
+ ///
+ /// [offset] is the location of the constructor invocation in the source file.
+ /// [target] is the constructor that is being called. [explicitTypeArguments]
+ /// is the set of type arguments explicitly provided, or `null` if no type
+ /// arguments were provided. [forEachArgument] is a callback which can be
+ /// used to iterate through all constructor arguments (both named and
+ /// positional). [setClassType] is a callback which can be used to record the
+ /// inferred type.
+ DartType inferConstructorInvocation(
+ DartType typeContext,
+ bool typeNeeded,
+ int offset,
+ Constructor target,
+ List<DartType> explicitTypeArguments,
+ void forEachArgument(void callback(String name, E expression)),
+ void setClassType(InterfaceType type)) {
+ List<DartType> typesFromDownwardsInference;
+ InterfaceType inferredClassType;
+ Substitution substitution;
+ List<DartType> formalTypes;
+ List<DartType> actualTypes;
+ var targetClass = target.enclosingClass;
+ var targetTypeParameters = targetClass.typeParameters;
+ bool inferenceNeeded = explicitTypeArguments == null &&
+ strongMode &&
+ targetTypeParameters.isNotEmpty;
+ if (inferenceNeeded) {
+ typesFromDownwardsInference =
+ new List<DartType>.filled(targetTypeParameters.length, null);
+ inferredClassType = typeSchemaEnvironment.inferGenericFunctionOrType(
+ targetClass.typeParameters,
+ targetClass.thisType,
+ [],
+ [],
+ typeContext,
+ typesFromDownwardsInference);
+ substitution = Substitution.fromPairs(
+ targetTypeParameters, typesFromDownwardsInference);
+ } else {
+ inferredClassType = targetClass.rawType;
+ }
+ int i = 0;
+ forEachArgument((name, expression) {
+ DartType formalType = name != null
+ ? _getNamedParameterType(target.function, name)
+ : _getPositionalParameterType(target.function, i++);
+ DartType inferredFormalType = substitution != null
+ ? substitution.substituteType(formalType)
+ : formalType;
+ var expressionType =
+ inferExpression(expression, inferredFormalType, inferenceNeeded);
+ if (inferenceNeeded) {
+ formalTypes.add(formalType);
+ actualTypes.add(expressionType);
+ }
+ });
+ if (inferenceNeeded) {
+ inferredClassType = typeSchemaEnvironment.inferGenericFunctionOrType(
+ targetClass.typeParameters,
+ targetClass.thisType,
+ formalTypes,
+ actualTypes,
+ typeContext,
+ typesFromDownwardsInference);
+ instrumentation?.record(Uri.parse(uri), offset, 'typeArgs',
+ new InstrumentationValueForTypeArgs(inferredClassType.typeArguments));
+ setClassType(inferredClassType);
+ }
+ return typeNeeded ? inferredClassType : null;
+ }
+
/// Maps the type of a variable's initializer expression to the correct
/// inferred type for the variable.
DartType inferDeclarationType(DartType initializerType) {
@@ -395,6 +478,32 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> {
DartType typeContext, bool typeNeeded, DartType declaredType, E value) {
return inferExpression(value, declaredType, typeNeeded);
}
+
+ DartType _getNamedParameterType(FunctionNode function, String name) {
+ // TODO(paulberry): is there a kernel function that does this binary search?
+ int lower = 0;
+ int upper = function.namedParameters.length - 1;
+ while (lower <= upper) {
+ int pivot = (lower + upper) ~/ 2;
+ int comparison = name.compareTo(function.namedParameters[pivot].name);
+ if (comparison == 0) {
+ return function.namedParameters[pivot].type;
+ } else if (comparison < 0) {
+ upper = pivot - 1;
+ } else {
+ lower = pivot + 1;
+ }
+ }
+ return const DynamicType();
+ }
+
+ DartType _getPositionalParameterType(FunctionNode function, int i) {
+ if (i < function.positionalParameters.length) {
+ return function.positionalParameters[i].type;
+ } else {
+ return const DynamicType();
+ }
+ }
}
/// Keeps track of information about the innermost function or closure being

Powered by Google App Engine
This is Rietveld 408576698