@@ -2197,9 +2197,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase
2197
2197
int ? stackBase;
2198
2198
assert (checkStackBase (element, stackBase = stackHeight));
2199
2199
2200
- CollectionElementInferenceContext context =
2201
- new CollectionElementInferenceContext (
2202
- typeContext : inferredTypeArgument,
2200
+ ListAndSetElementInferenceContext context =
2201
+ new ListAndSetElementInferenceContext (
2202
+ inferredTypeArgument : inferredTypeArgument,
2203
2203
inferredSpreadTypes: inferredSpreadTypes,
2204
2204
inferredConditionTypes: inferredConditionTypes);
2205
2205
analyzeIfCaseElement (
@@ -2972,6 +2972,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase
2972
2972
entry, receiverType, keyType, valueType, result, body);
2973
2973
} else if (entry is IfMapEntry ) {
2974
2974
_translateIfEntry (entry, receiverType, keyType, valueType, result, body);
2975
+ } else if (entry is IfCaseMapEntry ) {
2976
+ _translateIfCaseEntry (
2977
+ entry, receiverType, keyType, valueType, result, body);
2975
2978
} else if (entry is ForMapEntry ) {
2976
2979
_translateForEntry (entry, receiverType, keyType, valueType, result, body);
2977
2980
} else if (entry is ForInMapEntry ) {
@@ -3016,6 +3019,35 @@ class InferenceVisitorImpl extends InferenceVisitorBase
3016
3019
body.add (ifStatement);
3017
3020
}
3018
3021
3022
+ void _translateIfCaseEntry (
3023
+ IfCaseMapEntry entry,
3024
+ InterfaceType receiverType,
3025
+ DartType keyType,
3026
+ DartType valueType,
3027
+ VariableDeclaration result,
3028
+ List <Statement > body) {
3029
+ List <Statement > thenBody = [];
3030
+ _translateEntry (
3031
+ entry.then, receiverType, keyType, valueType, result, thenBody);
3032
+ List <Statement >? elseBody;
3033
+ if (entry.otherwise != null ) {
3034
+ _translateEntry (entry.otherwise! , receiverType, keyType, valueType,
3035
+ result, elseBody = < Statement > []);
3036
+ }
3037
+ Statement thenStatement =
3038
+ thenBody.length == 1 ? thenBody.first : _createBlock (thenBody);
3039
+ Statement ? elseStatement;
3040
+ if (elseBody != null && elseBody.isNotEmpty) {
3041
+ elseStatement =
3042
+ elseBody.length == 1 ? elseBody.first : _createBlock (elseBody);
3043
+ }
3044
+ IfStatement ifStatement = _createIf (
3045
+ entry.fileOffset, entry.expression, thenStatement, elseStatement);
3046
+ libraryBuilder.loader.dataForTesting? .registerAlias (entry, ifStatement);
3047
+ body.addAll (entry.replacement);
3048
+ body.add (ifStatement);
3049
+ }
3050
+
3019
3051
void _translateForEntry (
3020
3052
ForMapEntry entry,
3021
3053
InterfaceType receiverType,
@@ -3911,7 +3943,18 @@ class InferenceVisitorImpl extends InferenceVisitorBase
3911
3943
flowAnalysis.ifStatement_end (entry.otherwise != null );
3912
3944
return entry;
3913
3945
} else if (entry is IfCaseMapEntry ) {
3914
- // TODO(cstefantsova): Pass an appropriate context message.
3946
+ int ? stackBase;
3947
+ assert (checkStackBase (entry, stackBase = stackHeight));
3948
+
3949
+ MapEntryInferenceContext context = new MapEntryInferenceContext (
3950
+ inferredKeyType: inferredKeyType,
3951
+ inferredValueType: inferredValueType,
3952
+ spreadContext: spreadContext,
3953
+ actualTypes: actualTypes,
3954
+ actualTypesForSet: actualTypesForSet,
3955
+ offsets: offsets,
3956
+ inferredSpreadTypes: inferredSpreadTypes,
3957
+ inferredConditionTypes: inferredConditionTypes);
3915
3958
analyzeIfCaseElement (
3916
3959
node: entry,
3917
3960
expression: entry.expression,
@@ -3924,9 +3967,86 @@ class InferenceVisitorImpl extends InferenceVisitorBase
3924
3967
guard: entry.patternGuard.guard,
3925
3968
ifTrue: entry.then,
3926
3969
ifFalse: entry.otherwise,
3927
- context: null );
3928
- // TODO(cstefantsova): Implement inference for if-case map entries.
3929
- throw new UnimplementedError ();
3970
+ context: context);
3971
+ if (entry.otherwise != null ) {
3972
+ DartType actualValueType = actualTypes.removeLast ();
3973
+ DartType actualKeyType = actualTypes.removeLast ();
3974
+ int length = actualTypes.length;
3975
+ actualTypes[length - 2 ] = typeSchemaEnvironment.getStandardUpperBound (
3976
+ actualKeyType, actualTypes[length - 2 ],
3977
+ isNonNullableByDefault: libraryBuilder.isNonNullableByDefault);
3978
+ actualTypes[length - 1 ] = typeSchemaEnvironment.getStandardUpperBound (
3979
+ actualValueType, actualTypes[length - 1 ],
3980
+ isNonNullableByDefault: libraryBuilder.isNonNullableByDefault);
3981
+ DartType actualTypeForSet = actualTypesForSet.removeLast ();
3982
+ int lengthForSet = actualTypesForSet.length;
3983
+ actualTypesForSet[lengthForSet - 1 ] =
3984
+ typeSchemaEnvironment.getStandardUpperBound (
3985
+ actualTypeForSet, actualTypesForSet[lengthForSet - 1 ],
3986
+ isNonNullableByDefault: libraryBuilder.isNonNullableByDefault);
3987
+ }
3988
+
3989
+ assert (checkStack (entry, stackBase, [
3990
+ /* ifFalse = */ unionOfKinds (
3991
+ [ValueKinds .MapLiteralEntryOrNull , ValueKinds .ExpressionOrNull ]),
3992
+ /* ifTrue = */ unionOfKinds (
3993
+ [ValueKinds .MapLiteralEntry , ValueKinds .Expression ]),
3994
+ /* guard = */ ValueKinds .ExpressionOrNull ,
3995
+ /* pattern = */ ValueKinds .Pattern ,
3996
+ /* scrutinee = */ ValueKinds .Expression ,
3997
+ ]));
3998
+
3999
+ Object ? rewrite = popRewrite (NullValues .Expression );
4000
+ if (! identical (entry.otherwise, rewrite)) {
4001
+ entry.otherwise = (rewrite as MapLiteralEntry ? )? ..parent = entry;
4002
+ }
4003
+
4004
+ rewrite = popRewrite ();
4005
+ if (! identical (entry.then, rewrite)) {
4006
+ entry.then = (rewrite as MapLiteralEntry )..parent = entry;
4007
+ }
4008
+
4009
+ PatternGuard patternGuard = entry.patternGuard;
4010
+ rewrite = popRewrite (NullValues .Expression );
4011
+ if (! identical (patternGuard.guard, rewrite)) {
4012
+ patternGuard.guard = (rewrite as Expression ? )? ..parent = patternGuard;
4013
+ }
4014
+
4015
+ rewrite = popRewrite ();
4016
+ if (! identical (patternGuard.pattern, rewrite)) {
4017
+ patternGuard.pattern = (rewrite as Pattern )..parent = patternGuard;
4018
+ }
4019
+
4020
+ rewrite = popRewrite ();
4021
+ if (! identical (entry.expression, rewrite)) {
4022
+ entry.expression = (rewrite as Expression )..parent = patternGuard;
4023
+ }
4024
+
4025
+ MatchingCache matchingCache = createMatchingCache ();
4026
+ MatchingExpressionVisitor matchingExpressionVisitor =
4027
+ new MatchingExpressionVisitor (matchingCache);
4028
+ // TODO(cstefantsova): Provide a more precise scrutinee type.
4029
+ CacheableExpression matchedExpression = matchingCache
4030
+ .createRootExpression (entry.expression, const DynamicType ());
4031
+ DelayedExpression matchingExpression = matchingExpressionVisitor
4032
+ .visitPattern (entry.patternGuard.pattern, matchedExpression);
4033
+
4034
+ matchingExpression.registerUse ();
4035
+
4036
+ Expression condition =
4037
+ matchingExpression.createExpression (typeSchemaEnvironment);
4038
+ Expression ? guard = entry.patternGuard.guard;
4039
+ if (guard != null ) {
4040
+ condition =
4041
+ createAndExpression (condition, guard, fileOffset: guard.fileOffset);
4042
+ }
4043
+ entry.expression = condition;
4044
+ entry.replacement = [
4045
+ ...entry.patternGuard.pattern.declaredVariables,
4046
+ ...matchingCache.declarations,
4047
+ ];
4048
+
4049
+ return entry;
3930
4050
} else if (entry is ForMapEntry ) {
3931
4051
// TODO(johnniwinther): Use _visitStatements instead.
3932
4052
List <VariableDeclaration >? variables;
@@ -10587,17 +10707,37 @@ class InferenceVisitorImpl extends InferenceVisitorBase
10587
10707
}
10588
10708
10589
10709
@override
10590
- void dispatchCollectionElement (covariant Expression element,
10710
+ void dispatchCollectionElement (covariant TreeNode element,
10591
10711
covariant CollectionElementInferenceContext context) {
10592
- ExpressionInferenceResult inferenceResult = inferElement (
10593
- element,
10594
- context.typeContext,
10595
- context.inferredSpreadTypes,
10596
- context.inferredConditionTypes);
10597
- // TODO(cstefantsova): Should the key to the map be [element] instead?
10598
- context.inferredConditionTypes[inferenceResult.expression] =
10599
- inferenceResult.inferredType;
10600
- pushRewrite (inferenceResult.expression);
10712
+ if (element is Expression ) {
10713
+ context as ListAndSetElementInferenceContext ;
10714
+ ExpressionInferenceResult inferenceResult = inferElement (
10715
+ element,
10716
+ context.inferredTypeArgument,
10717
+ context.inferredSpreadTypes,
10718
+ context.inferredConditionTypes);
10719
+ // TODO(cstefantsova): Should the key to the map be [element] instead?
10720
+ context.inferredConditionTypes[inferenceResult.expression] =
10721
+ inferenceResult.inferredType;
10722
+ pushRewrite (inferenceResult.expression);
10723
+ } else if (element is MapLiteralEntry ) {
10724
+ context as MapEntryInferenceContext ;
10725
+ element = inferMapEntry (
10726
+ element,
10727
+ element.parent! ,
10728
+ context.inferredKeyType,
10729
+ context.inferredValueType,
10730
+ context.spreadContext,
10731
+ context.actualTypes,
10732
+ context.actualTypesForSet,
10733
+ context.inferredSpreadTypes,
10734
+ context.inferredConditionTypes,
10735
+ context.offsets);
10736
+ pushRewrite (element);
10737
+ } else {
10738
+ problems.unsupported (
10739
+ "${element .runtimeType }" , element.fileOffset, helper.uri);
10740
+ }
10601
10741
}
10602
10742
10603
10743
@override
@@ -10811,13 +10951,46 @@ extension on SwitchCase {
10811
10951
}
10812
10952
}
10813
10953
10814
- class CollectionElementInferenceContext {
10815
- DartType typeContext;
10954
+ abstract class CollectionElementInferenceContext {
10816
10955
Map <TreeNode , DartType > inferredSpreadTypes;
10817
10956
Map <Expression , DartType > inferredConditionTypes;
10818
10957
10819
10958
CollectionElementInferenceContext (
10820
- {required this .typeContext,
10821
- required this .inferredSpreadTypes,
10959
+ {required this .inferredSpreadTypes,
10822
10960
required this .inferredConditionTypes});
10823
10961
}
10962
+
10963
+ class ListAndSetElementInferenceContext
10964
+ extends CollectionElementInferenceContext {
10965
+ DartType inferredTypeArgument;
10966
+
10967
+ ListAndSetElementInferenceContext (
10968
+ {required this .inferredTypeArgument,
10969
+ required Map <TreeNode , DartType > inferredSpreadTypes,
10970
+ required Map <Expression , DartType > inferredConditionTypes})
10971
+ : super (
10972
+ inferredSpreadTypes: inferredSpreadTypes,
10973
+ inferredConditionTypes: inferredConditionTypes);
10974
+ }
10975
+
10976
+ class MapEntryInferenceContext extends CollectionElementInferenceContext {
10977
+ DartType inferredKeyType;
10978
+ DartType inferredValueType;
10979
+ DartType spreadContext;
10980
+ List <DartType > actualTypes;
10981
+ List <DartType > actualTypesForSet;
10982
+ _MapLiteralEntryOffsets offsets;
10983
+
10984
+ MapEntryInferenceContext (
10985
+ {required this .inferredKeyType,
10986
+ required this .inferredValueType,
10987
+ required this .spreadContext,
10988
+ required this .actualTypes,
10989
+ required this .actualTypesForSet,
10990
+ required this .offsets,
10991
+ required Map <TreeNode , DartType > inferredSpreadTypes,
10992
+ required Map <Expression , DartType > inferredConditionTypes})
10993
+ : super (
10994
+ inferredSpreadTypes: inferredSpreadTypes,
10995
+ inferredConditionTypes: inferredConditionTypes);
10996
+ }
0 commit comments