Skip to content

Commit 0ae5ca1

Browse files
stereotype441Commit Bot
authored and
Commit Bot
committed
Rework type inference logic to avoid redundant constraint gathering.
Previously, the front end would perform downwards and upwards inference using separate TypeConstraintGatherer objects. This meant that any constraint gathering work performed during downwards inference had to be repeated during upwards inference. This change avoids the extra work by using a single TypeConstraintGatherer object for both downwards and upwards inference. This should help pave the way to implementing support for dart-lang/language#731 (improved inference for fold etc.) Change-Id: Ib4031ab1397d6a8547a705f386632de0e4dd1a2b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241120 Reviewed-by: Johnni Winther <[email protected]> Reviewed-by: Chloe Stefantsova <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent e5c83a3 commit 0ae5ca1

7 files changed

+181
-153
lines changed

pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import '../fasta_codes.dart';
1919
import '../names.dart';
2020
import '../problems.dart' show unhandled;
2121
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
22+
import '../type_inference/type_constraint_gatherer.dart';
2223
import '../type_inference/type_inference_engine.dart';
2324
import '../type_inference/type_inferrer.dart';
2425
import '../type_inference/type_schema.dart' show UnknownType;
@@ -2027,17 +2028,20 @@ class InferenceVisitor
20272028
inferredSpreadTypes = new Map<TreeNode, DartType>.identity();
20282029
inferredConditionTypes = new Map<Expression, DartType>.identity();
20292030
}
2031+
TypeConstraintGatherer? gatherer;
20302032
if (inferenceNeeded) {
20312033
inferredTypes = [const UnknownType()];
2032-
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
2034+
gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
20332035
listType,
20342036
listClass.typeParameters,
2035-
null,
2036-
null,
20372037
typeContext,
2038-
inferredTypes,
20392038
inferrer.libraryBuilder.library,
20402039
isConst: node.isConst);
2040+
inferrer.typeSchemaEnvironment.downwardsInfer(
2041+
gatherer,
2042+
listClass.typeParameters,
2043+
inferredTypes,
2044+
inferrer.libraryBuilder.library);
20412045
inferredTypeArgument = inferredTypes[0];
20422046
if (inferrer.dataForTesting != null) {
20432047
inferrer.dataForTesting!.typeInferenceResult
@@ -2063,12 +2067,10 @@ class InferenceVisitor
20632067
}
20642068
}
20652069
if (inferenceNeeded) {
2066-
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
2067-
listType,
2070+
gatherer!.constrainArguments(formalTypes!, actualTypes!);
2071+
inferrer.typeSchemaEnvironment.upwardsInfer(
2072+
gatherer,
20682073
listClass.typeParameters,
2069-
formalTypes,
2070-
actualTypes,
2071-
typeContext,
20722074
inferredTypes!,
20732075
inferrer.libraryBuilder.library);
20742076
inferredTypeArgument = inferredTypes[0];
@@ -2711,17 +2713,20 @@ class InferenceVisitor
27112713
inferredSpreadTypes = new Map<TreeNode, DartType>.identity();
27122714
inferredConditionTypes = new Map<Expression, DartType>.identity();
27132715
}
2716+
TypeConstraintGatherer? gatherer;
27142717
if (inferenceNeeded) {
27152718
inferredTypes = [noInferredType, noInferredType];
2716-
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
2719+
gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
27172720
mapType,
27182721
mapClass.typeParameters,
2719-
null,
2720-
null,
27212722
typeContext,
2722-
inferredTypes,
27232723
inferrer.libraryBuilder.library,
27242724
isConst: node.isConst);
2725+
inferrer.typeSchemaEnvironment.downwardsInfer(
2726+
gatherer,
2727+
mapClass.typeParameters,
2728+
inferredTypes,
2729+
inferrer.libraryBuilder.library);
27252730
inferredKeyType = inferredTypes[0];
27262731
inferredValueType = inferredTypes[1];
27272732
if (inferrer.dataForTesting != null) {
@@ -2792,22 +2797,25 @@ class InferenceVisitor
27922797
}
27932798

27942799
List<DartType> inferredTypesForSet = <DartType>[noInferredType];
2795-
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
2796-
setType,
2800+
// Note: we don't use the previously created gatherer because it was set
2801+
// up presuming that the literal would be a map; we now know that it
2802+
// needs to be a set.
2803+
TypeConstraintGatherer gatherer = inferrer.typeSchemaEnvironment
2804+
.setupGenericTypeInference(
2805+
setType,
2806+
inferrer.coreTypes.setClass.typeParameters,
2807+
typeContext,
2808+
inferrer.libraryBuilder.library,
2809+
isConst: node.isConst);
2810+
inferrer.typeSchemaEnvironment.downwardsInfer(
2811+
gatherer,
27972812
inferrer.coreTypes.setClass.typeParameters,
2798-
null,
2799-
null,
2800-
typeContext,
28012813
inferredTypesForSet,
2802-
inferrer.libraryBuilder.library,
2803-
isConst: node.isConst);
2804-
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
2805-
inferrer.coreTypes.thisInterfaceType(inferrer.coreTypes.setClass,
2806-
inferrer.libraryBuilder.nonNullable),
2814+
inferrer.libraryBuilder.library);
2815+
gatherer.constrainArguments(formalTypesForSet, actualTypesForSet!);
2816+
inferrer.typeSchemaEnvironment.upwardsInfer(
2817+
gatherer,
28072818
inferrer.coreTypes.setClass.typeParameters,
2808-
formalTypesForSet,
2809-
actualTypesForSet,
2810-
typeContext,
28112819
inferredTypesForSet,
28122820
inferrer.libraryBuilder.library);
28132821
DartType inferredTypeArgument = inferredTypesForSet[0];
@@ -2855,12 +2863,10 @@ class InferenceVisitor
28552863
NeverType.fromNullability(inferrer.libraryBuilder.nonNullable),
28562864
replacement);
28572865
}
2858-
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
2859-
mapType,
2866+
gatherer!.constrainArguments(formalTypes!, actualTypes!);
2867+
inferrer.typeSchemaEnvironment.upwardsInfer(
2868+
gatherer,
28602869
mapClass.typeParameters,
2861-
formalTypes,
2862-
actualTypes,
2863-
typeContext,
28642870
inferredTypes!,
28652871
inferrer.libraryBuilder.library);
28662872
inferredKeyType = inferredTypes[0];
@@ -5977,17 +5983,20 @@ class InferenceVisitor
59775983
inferredSpreadTypes = new Map<TreeNode, DartType>.identity();
59785984
inferredConditionTypes = new Map<Expression, DartType>.identity();
59795985
}
5986+
TypeConstraintGatherer? gatherer;
59805987
if (inferenceNeeded) {
59815988
inferredTypes = [const UnknownType()];
5982-
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
5989+
gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
59835990
setType,
59845991
setClass.typeParameters,
5985-
null,
5986-
null,
59875992
typeContext,
5988-
inferredTypes,
59895993
inferrer.libraryBuilder.library,
59905994
isConst: node.isConst);
5995+
inferrer.typeSchemaEnvironment.downwardsInfer(
5996+
gatherer,
5997+
setClass.typeParameters,
5998+
inferredTypes,
5999+
inferrer.libraryBuilder.library);
59916000
inferredTypeArgument = inferredTypes[0];
59926001
if (inferrer.dataForTesting != null) {
59936002
inferrer.dataForTesting!.typeInferenceResult
@@ -6013,12 +6022,10 @@ class InferenceVisitor
60136022
}
60146023
}
60156024
if (inferenceNeeded) {
6016-
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
6017-
setType,
6025+
gatherer!.constrainArguments(formalTypes!, actualTypes!);
6026+
inferrer.typeSchemaEnvironment.upwardsInfer(
6027+
gatherer,
60186028
setClass.typeParameters,
6019-
formalTypes,
6020-
actualTypes,
6021-
typeContext,
60226029
inferredTypes!,
60236030
inferrer.libraryBuilder.library);
60246031
inferredTypeArgument = inferredTypes[0];

pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ abstract class TypeConstraintGatherer {
4545
void addLowerBound(
4646
TypeConstraint constraint, DartType lower, Library clientLibrary);
4747

48+
/// Applies all the argument constraints implied by trying to make
49+
/// [actualTypes] assignable to [formalTypes].
50+
void constrainArguments(
51+
List<DartType> formalTypes, List<DartType> actualTypes) {
52+
assert(formalTypes.length == actualTypes.length);
53+
for (int i = 0; i < formalTypes.length; i++) {
54+
// Try to pass each argument to each parameter, recording any type
55+
// parameter bounds that were implied by this assignment.
56+
tryConstrainLower(formalTypes[i], actualTypes[i]);
57+
}
58+
}
59+
4860
Member? getInterfaceMember(Class class_, Name name, {bool setter: false});
4961

5062
InterfaceType? getTypeAsInstanceOf(InterfaceType type, Class superclass,

pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -916,8 +916,12 @@ class TypeInferrerImpl implements TypeInferrer {
916916
DartType onType = extension.onType;
917917
List<DartType> inferredTypes =
918918
new List<DartType>.filled(typeParameters.length, const UnknownType());
919-
typeSchemaEnvironment.inferGenericFunctionOrType(null, typeParameters,
920-
[onType], [receiverType], null, inferredTypes, libraryBuilder.library);
919+
TypeConstraintGatherer gatherer =
920+
typeSchemaEnvironment.setupGenericTypeInference(
921+
null, typeParameters, null, libraryBuilder.library);
922+
gatherer.constrainArguments([onType], [receiverType]);
923+
typeSchemaEnvironment.upwardsInfer(
924+
gatherer, typeParameters, inferredTypes, libraryBuilder.library);
921925
return inferredTypes;
922926
}
923927

@@ -2305,6 +2309,7 @@ class TypeInferrerImpl implements TypeInferrer {
23052309
hoistedExpressions = localHoistedExpressions = <VariableDeclaration>[];
23062310
}
23072311

2312+
TypeConstraintGatherer? gatherer;
23082313
if (inferenceNeeded) {
23092314
// ignore: unnecessary_null_comparison
23102315
if (isConst && typeContext != null) {
@@ -2317,16 +2322,15 @@ class TypeInferrerImpl implements TypeInferrer {
23172322
}
23182323
inferredTypes = new List<DartType>.filled(
23192324
calleeTypeParameters.length, const UnknownType());
2320-
typeSchemaEnvironment.inferGenericFunctionOrType(
2325+
gatherer = typeSchemaEnvironment.setupGenericTypeInference(
23212326
isNonNullableByDefault
23222327
? calleeType.returnType
23232328
: legacyErasure(calleeType.returnType),
23242329
calleeTypeParameters,
2325-
null,
2326-
null,
23272330
typeContext,
2328-
inferredTypes,
23292331
libraryBuilder.library);
2332+
typeSchemaEnvironment.downwardsInfer(gatherer, calleeTypeParameters,
2333+
inferredTypes, libraryBuilder.library);
23302334
substitution =
23312335
Substitution.fromPairs(calleeTypeParameters, inferredTypes);
23322336
} else if (explicitTypeArguments != null &&
@@ -2588,14 +2592,9 @@ class TypeInferrerImpl implements TypeInferrer {
25882592
}
25892593

25902594
if (inferenceNeeded) {
2591-
typeSchemaEnvironment.inferGenericFunctionOrType(
2592-
calleeType.returnType,
2593-
calleeTypeParameters,
2594-
formalTypes,
2595-
actualTypes,
2596-
typeContext,
2597-
inferredTypes!,
2598-
libraryBuilder.library);
2595+
gatherer!.constrainArguments(formalTypes!, actualTypes!);
2596+
typeSchemaEnvironment.upwardsInfer(gatherer, calleeTypeParameters,
2597+
inferredTypes!, libraryBuilder.library);
25992598
assert(inferredTypes.every((type) => isKnown(type)),
26002599
"Unknown type(s) in inferred types: $inferredTypes.");
26012600
assert(inferredTypes.every((type) => !hasPromotedTypeVariable(type)),
@@ -4138,14 +4137,11 @@ class TypeInferrerImpl implements TypeInferrer {
41384137
List<DartType> inferredTypes = new List<DartType>.filled(
41394138
typeParameters.length, const UnknownType());
41404139
FunctionType instantiatedType = functionType.withoutTypeParameters;
4141-
typeSchemaEnvironment.inferGenericFunctionOrType(
4142-
instantiatedType,
4143-
typeParameters,
4144-
[],
4145-
[],
4146-
context,
4147-
inferredTypes,
4148-
libraryBuilder.library);
4140+
TypeConstraintGatherer gatherer =
4141+
typeSchemaEnvironment.setupGenericTypeInference(instantiatedType,
4142+
typeParameters, context, libraryBuilder.library);
4143+
typeSchemaEnvironment.upwardsInfer(
4144+
gatherer, typeParameters, inferredTypes, libraryBuilder.library);
41494145
Substitution substitution =
41504146
Substitution.fromPairs(typeParameters, inferredTypes);
41514147
tearoffType = substitution.substituteType(instantiatedType);

0 commit comments

Comments
 (0)