Skip to content

Commit 0d636e5

Browse files
stereotype441Commit Bot
authored and
Commit Bot
committed
Ensure that partial inference results aren't refined by later partial inference stages.
As part of the implementation of dart-lang/language#731 (improved inference for fold etc.), I expanded the front end's type inference logic so that instead of just having a downward phase and an upward phase, it could have 3 or more phases. The function that previously did downward inference became repurposed to do "partial inference" (which could either be the first, downward stage, or a later, horizontal stage). However, I failed to generalize the logic that prevents types assigned by one inference stage from being refined by later stages--previously this logic was only needed for upward inference, but now it's needed for horizontal inference stages as well. (This logic is needed because of Dart's "runtime checked covariance" behavior--it means that we want to stick with the type from downward inference, even if a later horizontal inference stage is able to find a more precise type, because that more precise type may lead to runtime failures). As part of this change I've re-architected the inference methods so that they are responsible for creating and returning the list of inferred types. This makes the inference logic more similar between the front end and analyzer, and is easier to read IMHO. The total number of list allocations is the same as before. Change-Id: I19bfcede9c2968e50f110b571164549f16495217 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243707 Reviewed-by: Chloe Stefantsova <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 51d578c commit 0d636e5

13 files changed

+189
-113
lines changed

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

Lines changed: 25 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2030,23 +2030,15 @@ class InferenceVisitor
20302030
}
20312031
TypeConstraintGatherer? gatherer;
20322032
if (inferenceNeeded) {
2033-
inferredTypes = [const UnknownType()];
20342033
gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
20352034
listType,
20362035
listClass.typeParameters,
20372036
typeContext,
20382037
inferrer.libraryBuilder.library,
20392038
isConst: node.isConst);
2040-
inferrer.typeSchemaEnvironment.partialInfer(
2041-
gatherer,
2042-
listClass.typeParameters,
2043-
inferredTypes,
2044-
inferrer.libraryBuilder.library);
2039+
inferredTypes = inferrer.typeSchemaEnvironment.partialInfer(gatherer,
2040+
listClass.typeParameters, null, inferrer.libraryBuilder.library);
20452041
inferredTypeArgument = inferredTypes[0];
2046-
if (inferrer.dataForTesting != null) {
2047-
inferrer.dataForTesting!.typeInferenceResult
2048-
.inferredTypeArguments[node] = inferredTypes;
2049-
}
20502042
} else {
20512043
inferredTypeArgument = node.typeArgument;
20522044
}
@@ -2068,11 +2060,15 @@ class InferenceVisitor
20682060
}
20692061
if (inferenceNeeded) {
20702062
gatherer!.constrainArguments(formalTypes!, actualTypes!);
2071-
inferrer.typeSchemaEnvironment.upwardsInfer(
2063+
inferredTypes = inferrer.typeSchemaEnvironment.upwardsInfer(
20722064
gatherer,
20732065
listClass.typeParameters,
20742066
inferredTypes!,
20752067
inferrer.libraryBuilder.library);
2068+
if (inferrer.dataForTesting != null) {
2069+
inferrer.dataForTesting!.typeInferenceResult
2070+
.inferredTypeArguments[node] = inferredTypes;
2071+
}
20762072
inferredTypeArgument = inferredTypes[0];
20772073
inferrer.instrumentation?.record(
20782074
inferrer.uriForInstrumentation,
@@ -2715,24 +2711,16 @@ class InferenceVisitor
27152711
}
27162712
TypeConstraintGatherer? gatherer;
27172713
if (inferenceNeeded) {
2718-
inferredTypes = [noInferredType, noInferredType];
27192714
gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
27202715
mapType,
27212716
mapClass.typeParameters,
27222717
typeContext,
27232718
inferrer.libraryBuilder.library,
27242719
isConst: node.isConst);
2725-
inferrer.typeSchemaEnvironment.partialInfer(
2726-
gatherer,
2727-
mapClass.typeParameters,
2728-
inferredTypes,
2729-
inferrer.libraryBuilder.library);
2720+
inferredTypes = inferrer.typeSchemaEnvironment.partialInfer(gatherer,
2721+
mapClass.typeParameters, null, inferrer.libraryBuilder.library);
27302722
inferredKeyType = inferredTypes[0];
27312723
inferredValueType = inferredTypes[1];
2732-
if (inferrer.dataForTesting != null) {
2733-
inferrer.dataForTesting!.typeInferenceResult
2734-
.inferredTypeArguments[node] = inferredTypes;
2735-
}
27362724
} else {
27372725
inferredKeyType = node.keyType;
27382726
inferredValueType = node.valueType;
@@ -2796,7 +2784,6 @@ class InferenceVisitor
27962784
formalTypesForSet.add(setType.typeArguments[0]);
27972785
}
27982786

2799-
List<DartType> inferredTypesForSet = <DartType>[noInferredType];
28002787
// Note: we don't use the previously created gatherer because it was set
28012788
// up presuming that the literal would be a map; we now know that it
28022789
// needs to be a set.
@@ -2807,13 +2794,11 @@ class InferenceVisitor
28072794
typeContext,
28082795
inferrer.libraryBuilder.library,
28092796
isConst: node.isConst);
2810-
inferrer.typeSchemaEnvironment.partialInfer(
2811-
gatherer,
2812-
inferrer.coreTypes.setClass.typeParameters,
2813-
inferredTypesForSet,
2814-
inferrer.libraryBuilder.library);
2797+
List<DartType> inferredTypesForSet = inferrer.typeSchemaEnvironment
2798+
.partialInfer(gatherer, inferrer.coreTypes.setClass.typeParameters,
2799+
null, inferrer.libraryBuilder.library);
28152800
gatherer.constrainArguments(formalTypesForSet, actualTypesForSet!);
2816-
inferrer.typeSchemaEnvironment.upwardsInfer(
2801+
inferredTypesForSet = inferrer.typeSchemaEnvironment.upwardsInfer(
28172802
gatherer,
28182803
inferrer.coreTypes.setClass.typeParameters,
28192804
inferredTypesForSet,
@@ -2864,11 +2849,15 @@ class InferenceVisitor
28642849
replacement);
28652850
}
28662851
gatherer!.constrainArguments(formalTypes!, actualTypes!);
2867-
inferrer.typeSchemaEnvironment.upwardsInfer(
2852+
inferredTypes = inferrer.typeSchemaEnvironment.upwardsInfer(
28682853
gatherer,
28692854
mapClass.typeParameters,
28702855
inferredTypes!,
28712856
inferrer.libraryBuilder.library);
2857+
if (inferrer.dataForTesting != null) {
2858+
inferrer.dataForTesting!.typeInferenceResult
2859+
.inferredTypeArguments[node] = inferredTypes;
2860+
}
28722861
inferredKeyType = inferredTypes[0];
28732862
inferredValueType = inferredTypes[1];
28742863
inferrer.instrumentation?.record(
@@ -5985,23 +5974,15 @@ class InferenceVisitor
59855974
}
59865975
TypeConstraintGatherer? gatherer;
59875976
if (inferenceNeeded) {
5988-
inferredTypes = [const UnknownType()];
59895977
gatherer = inferrer.typeSchemaEnvironment.setupGenericTypeInference(
59905978
setType,
59915979
setClass.typeParameters,
59925980
typeContext,
59935981
inferrer.libraryBuilder.library,
59945982
isConst: node.isConst);
5995-
inferrer.typeSchemaEnvironment.partialInfer(
5996-
gatherer,
5997-
setClass.typeParameters,
5998-
inferredTypes,
5999-
inferrer.libraryBuilder.library);
5983+
inferredTypes = inferrer.typeSchemaEnvironment.partialInfer(gatherer,
5984+
setClass.typeParameters, null, inferrer.libraryBuilder.library);
60005985
inferredTypeArgument = inferredTypes[0];
6001-
if (inferrer.dataForTesting != null) {
6002-
inferrer.dataForTesting!.typeInferenceResult
6003-
.inferredTypeArguments[node] = inferredTypes;
6004-
}
60055986
} else {
60065987
inferredTypeArgument = node.typeArgument;
60075988
}
@@ -6023,11 +6004,15 @@ class InferenceVisitor
60236004
}
60246005
if (inferenceNeeded) {
60256006
gatherer!.constrainArguments(formalTypes!, actualTypes!);
6026-
inferrer.typeSchemaEnvironment.upwardsInfer(
6007+
inferredTypes = inferrer.typeSchemaEnvironment.upwardsInfer(
60276008
gatherer,
60286009
setClass.typeParameters,
60296010
inferredTypes!,
60306011
inferrer.libraryBuilder.library);
6012+
if (inferrer.dataForTesting != null) {
6013+
inferrer.dataForTesting!.typeInferenceResult
6014+
.inferredTypeArguments[node] = inferredTypes;
6015+
}
60316016
inferredTypeArgument = inferredTypes[0];
60326017
inferrer.instrumentation?.record(
60336018
inferrer.uriForInstrumentation,

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,7 @@ class TypeInferrerImpl implements TypeInferrer {
978978
typeSchemaEnvironment.setupGenericTypeInference(
979979
null, typeParameters, null, libraryBuilder.library);
980980
gatherer.constrainArguments([onType], [receiverType]);
981-
typeSchemaEnvironment.upwardsInfer(
981+
inferredTypes = typeSchemaEnvironment.upwardsInfer(
982982
gatherer, typeParameters, inferredTypes, libraryBuilder.library);
983983
return inferredTypes;
984984
}
@@ -2378,17 +2378,15 @@ class TypeInferrerImpl implements TypeInferrer {
23782378
: coreTypes.objectLegacyRawType)
23792379
.substituteType(typeContext);
23802380
}
2381-
inferredTypes = new List<DartType>.filled(
2382-
calleeTypeParameters.length, const UnknownType());
23832381
gatherer = typeSchemaEnvironment.setupGenericTypeInference(
23842382
isNonNullableByDefault
23852383
? calleeType.returnType
23862384
: legacyErasure(calleeType.returnType),
23872385
calleeTypeParameters,
23882386
typeContext,
23892387
libraryBuilder.library);
2390-
typeSchemaEnvironment.partialInfer(gatherer, calleeTypeParameters,
2391-
inferredTypes, libraryBuilder.library);
2388+
inferredTypes = typeSchemaEnvironment.partialInfer(
2389+
gatherer, calleeTypeParameters, null, libraryBuilder.library);
23922390
substitution =
23932391
Substitution.fromPairs(calleeTypeParameters, inferredTypes);
23942392
} else if (explicitTypeArguments != null &&
@@ -2579,8 +2577,8 @@ class TypeInferrerImpl implements TypeInferrer {
25792577
: const [])
25802578
.planReconciliationStages()) {
25812579
if (gatherer != null && !isFirstStage) {
2582-
typeSchemaEnvironment.partialInfer(gatherer, calleeTypeParameters,
2583-
inferredTypes!, libraryBuilder.library);
2580+
inferredTypes = typeSchemaEnvironment.partialInfer(gatherer,
2581+
calleeTypeParameters, inferredTypes, libraryBuilder.library);
25842582
substitution =
25852583
Substitution.fromPairs(calleeTypeParameters, inferredTypes);
25862584
}
@@ -2706,8 +2704,8 @@ class TypeInferrerImpl implements TypeInferrer {
27062704
}
27072705

27082706
if (inferenceNeeded) {
2709-
typeSchemaEnvironment.upwardsInfer(gatherer!, calleeTypeParameters,
2710-
inferredTypes!, libraryBuilder.library);
2707+
inferredTypes = typeSchemaEnvironment.upwardsInfer(gatherer!,
2708+
calleeTypeParameters, inferredTypes!, libraryBuilder.library);
27112709
assert(inferredTypes.every((type) => isKnown(type)),
27122710
"Unknown type(s) in inferred types: $inferredTypes.");
27132711
assert(inferredTypes.every((type) => !hasPromotedTypeVariable(type)),
@@ -4255,7 +4253,7 @@ class TypeInferrerImpl implements TypeInferrer {
42554253
TypeConstraintGatherer gatherer =
42564254
typeSchemaEnvironment.setupGenericTypeInference(instantiatedType,
42574255
typeParameters, context, libraryBuilder.library);
4258-
typeSchemaEnvironment.upwardsInfer(
4256+
inferredTypes = typeSchemaEnvironment.upwardsInfer(
42594257
gatherer, typeParameters, inferredTypes, libraryBuilder.library);
42604258
Substitution substitution =
42614259
Substitution.fromPairs(typeParameters, inferredTypes);

0 commit comments

Comments
 (0)