Skip to content

Commit 41ef3a1

Browse files
srawlinsCommit Queue
authored andcommitted
analyzer: look at element types for const sets and maps
Fixes #54356 Change-Id: Iee17d4aee3173db9747cdd9c9a0cc4203abab226 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/400802 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent c1f5bab commit 41ef3a1

File tree

5 files changed

+218
-115
lines changed

5 files changed

+218
-115
lines changed

pkg/analyzer/lib/src/dart/constant/evaluation.dart

Lines changed: 35 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,13 +1013,7 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
10131013
: _typeProvider.dynamicType;
10141014
var listType = _typeProvider.listType(elementType);
10151015
var list = <DartObjectImpl>[];
1016-
return _buildListConstant(
1017-
list,
1018-
node.elements,
1019-
typeSystem,
1020-
listType,
1021-
elementType,
1022-
);
1016+
return _buildListConstant(list, node.elements, typeSystem, listType);
10231017
}
10241018

10251019
@override
@@ -1364,8 +1358,7 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
13641358
List<DartObjectImpl> list,
13651359
List<CollectionElement> elements,
13661360
TypeSystemImpl typeSystem,
1367-
DartType listType,
1368-
DartType elementType,
1361+
InterfaceType listType,
13691362
) {
13701363
for (var element in elements) {
13711364
switch (element) {
@@ -1388,11 +1381,9 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
13881381
case DartObjectImpl():
13891382
// If the condition is unknown, we mark this list as unknown.
13901383
if (condition.isUnknown) {
1391-
return DartObjectImpl.validWithUnknownValue(
1392-
typeSystem,
1393-
listType,
1394-
listElementType: elementType,
1395-
);
1384+
var elementType = listType.typeArguments.first;
1385+
return DartObjectImpl(
1386+
typeSystem, listType, ListState.unknown(elementType));
13961387
}
13971388
var conditionValue = condition.toBoolValue();
13981389
Constant? branchResult;
@@ -1401,20 +1392,10 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
14011392
CompileTimeErrorCode.NON_BOOL_CONDITION);
14021393
} else if (conditionValue) {
14031394
branchResult = _buildListConstant(
1404-
list,
1405-
[element.thenElement],
1406-
typeSystem,
1407-
listType,
1408-
elementType,
1409-
);
1395+
list, [element.thenElement], typeSystem, listType);
14101396
} else if (element.elseElement != null) {
14111397
branchResult = _buildListConstant(
1412-
list,
1413-
[element.elseElement!],
1414-
typeSystem,
1415-
listType,
1416-
elementType,
1417-
);
1398+
list, [element.elseElement!], typeSystem, listType);
14181399
}
14191400
if (branchResult is InvalidConstant) {
14201401
return branchResult;
@@ -1450,25 +1431,15 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
14501431
continue;
14511432
}
14521433
var result = _buildListConstant(
1453-
list,
1454-
[element.value],
1455-
typeSystem,
1456-
listType,
1457-
elementType,
1458-
);
1434+
list, [element.value], typeSystem, listType);
14591435
return result;
14601436
}
14611437
}
14621438
}
14631439

1464-
return DartObjectImpl(
1465-
typeSystem,
1466-
listType,
1467-
ListState(
1468-
elementType: elementType,
1469-
elements: list,
1470-
),
1471-
);
1440+
var elementType = listType.typeArguments.first;
1441+
return DartObjectImpl(typeSystem, listType,
1442+
ListState(elementType: elementType, elements: list));
14721443
}
14731444

14741445
/// Builds a map constant by adding the evaluated entries of [elements] to
@@ -1478,10 +1449,11 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
14781449
/// We return an [InvalidConstant] if the evaluation of any of the elements
14791450
/// failed.
14801451
Constant _buildMapConstant(
1481-
Map<DartObjectImpl, DartObjectImpl> map,
1482-
List<CollectionElement> elements,
1483-
TypeSystemImpl typeSystem,
1484-
DartType mapType) {
1452+
Map<DartObjectImpl, DartObjectImpl> map,
1453+
List<CollectionElement> elements,
1454+
TypeSystemImpl typeSystem,
1455+
InterfaceType mapType,
1456+
) {
14851457
for (var element in elements) {
14861458
switch (element) {
14871459
case Expression():
@@ -1498,8 +1470,10 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
14981470
case DartObjectImpl():
14991471
// If the condition is unknown, we mark this map as unknown.
15001472
if (condition.isUnknown) {
1501-
return DartObjectImpl.validWithUnknownValue(
1502-
typeSystem, mapType);
1473+
var keyType = mapType.typeArguments[0];
1474+
var valueType = mapType.typeArguments[1];
1475+
return DartObjectImpl(
1476+
typeSystem, mapType, MapState.unknown(keyType, valueType));
15031477
}
15041478
Constant? branchResult;
15051479
var conditionValue = condition.toBoolValue();
@@ -1556,7 +1530,10 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
15561530
}
15571531
}
15581532

1559-
return DartObjectImpl(typeSystem, mapType, MapState(map));
1533+
var keyType = mapType.typeArguments[0];
1534+
var valueType = mapType.typeArguments[1];
1535+
return DartObjectImpl(typeSystem, mapType,
1536+
MapState(keyType: keyType, valueType: valueType, entries: map));
15601537
}
15611538

15621539
/// Builds a set constant by adding the evaluated entries of [elements] to
@@ -1566,10 +1543,11 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
15661543
/// We return an [InvalidConstant] if the evaluation of any of the elements
15671544
/// failed.
15681545
Constant _buildSetConstant(
1569-
Set<DartObjectImpl> set,
1570-
List<CollectionElement> elements,
1571-
TypeSystemImpl typeSystem,
1572-
DartType setType) {
1546+
Set<DartObjectImpl> set,
1547+
List<CollectionElement> elements,
1548+
TypeSystemImpl typeSystem,
1549+
InterfaceType setType,
1550+
) {
15731551
for (var element in elements) {
15741552
switch (element) {
15751553
case Expression():
@@ -1591,8 +1569,9 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
15911569
case DartObjectImpl():
15921570
// If the condition is unknown, we mark this set as unknown.
15931571
if (condition.isUnknown) {
1594-
return DartObjectImpl.validWithUnknownValue(
1595-
typeSystem, setType);
1572+
var elementType = setType.typeArguments.first;
1573+
return DartObjectImpl(
1574+
typeSystem, setType, SetState.unknown(elementType));
15961575
}
15971576
Constant? branchResult;
15981577
var conditionValue = condition.toBoolValue();
@@ -1646,7 +1625,9 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
16461625
}
16471626
}
16481627

1649-
return DartObjectImpl(typeSystem, setType, SetState(set));
1628+
var elementType = setType.typeArguments.first;
1629+
return DartObjectImpl(
1630+
typeSystem, setType, SetState(elementType: elementType, elements: set));
16501631
}
16511632

16521633
/// Returns the result of concatenating [astNodes].

pkg/analyzer/lib/src/dart/constant/value.dart

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -211,24 +211,26 @@ class DartObjectImpl implements DartObject, Constant {
211211

212212
/// Create an object to represent an unknown value.
213213
factory DartObjectImpl.validWithUnknownValue(
214-
TypeSystemImpl typeSystem, DartType type,
215-
{DartType? listElementType}) {
214+
TypeSystemImpl typeSystem, DartType type) {
216215
if (type.isDartCoreBool) {
217216
return DartObjectImpl(typeSystem, type, BoolState.UNKNOWN_VALUE);
218217
} else if (type.isDartCoreDouble) {
219218
return DartObjectImpl(typeSystem, type, DoubleState.UNKNOWN_VALUE);
220219
} else if (type.isDartCoreInt) {
221220
return DartObjectImpl(typeSystem, type, IntState.UNKNOWN_VALUE);
222221
} else if (type.isDartCoreList) {
223-
return DartObjectImpl(
224-
typeSystem,
225-
type,
226-
ListState.unknown(
227-
listElementType ?? typeSystem.typeProvider.dynamicType));
222+
return DartObjectImpl(typeSystem, type,
223+
ListState.unknown(typeSystem.typeProvider.dynamicType));
228224
} else if (type.isDartCoreMap) {
229-
return DartObjectImpl(typeSystem, type, MapState.UNKNOWN);
225+
return DartObjectImpl(
226+
typeSystem,
227+
type,
228+
MapState.unknown(typeSystem.typeProvider.dynamicType,
229+
typeSystem.typeProvider.dynamicType),
230+
);
230231
} else if (type.isDartCoreSet) {
231-
return DartObjectImpl(typeSystem, type, SetState.UNKNOWN);
232+
return DartObjectImpl(typeSystem, type,
233+
SetState.unknown(typeSystem.typeProvider.dynamicType));
232234
} else if (type.isDartCoreString) {
233235
return DartObjectImpl(typeSystem, type, StringState.UNKNOWN_VALUE);
234236
}
@@ -2529,29 +2531,16 @@ class ListState extends InstanceState {
25292531
@override
25302532
final bool isUnknown;
25312533

2532-
factory ListState({
2534+
ListState({
25332535
required DartType elementType,
2534-
required List<DartObjectImpl> elements,
2535-
bool isUnknown = false,
2536-
}) {
2537-
elementType = elementType.extensionTypeErasure;
2538-
return ListState._(
2539-
elementType: elementType,
2540-
elements: elements,
2541-
isUnknown: isUnknown,
2542-
);
2543-
}
2536+
required this.elements,
2537+
this.isUnknown = false,
2538+
}) : elementType = elementType.extensionTypeErasure;
25442539

25452540
/// Creates a state that represents a list whose value is not known.
25462541
factory ListState.unknown(DartType elementType) =>
25472542
ListState(elementType: elementType, elements: [], isUnknown: true);
25482543

2549-
ListState._({
2550-
required this.elementType,
2551-
required this.elements,
2552-
required this.isUnknown,
2553-
});
2554-
25552544
@override
25562545
int get hashCode {
25572546
int value = 0;
@@ -2629,18 +2618,30 @@ class ListState extends InstanceState {
26292618

26302619
/// The state of an object representing a map.
26312620
class MapState extends InstanceState {
2632-
/// A state that represents a map whose value is not known.
2633-
static MapState UNKNOWN = MapState({}, isUnknown: true);
2621+
final DartType _keyType;
2622+
2623+
final DartType _valueType;
26342624

26352625
/// The entries in the map.
26362626
final Map<DartObjectImpl, DartObjectImpl> entries;
26372627

26382628
/// Whether the map contains an entry that has an unknown value.
26392629
final bool _isUnknown;
26402630

2641-
/// Initializes a newly created state to represent a map with the given
2631+
/// Initializes a newly created state to represent a set with the given
26422632
/// [entries].
2643-
MapState(this.entries, {bool isUnknown = false}) : _isUnknown = isUnknown;
2633+
MapState({
2634+
required DartType keyType,
2635+
required DartType valueType,
2636+
required this.entries,
2637+
bool isUnknown = false,
2638+
}) : _keyType = keyType.extensionTypeErasure,
2639+
_valueType = valueType.extensionTypeErasure,
2640+
_isUnknown = isUnknown;
2641+
2642+
/// Creates a state that represents a map whose value is not known.
2643+
factory MapState.unknown(DartType keyType, DartType valueType) => MapState(
2644+
keyType: keyType, valueType: valueType, entries: {}, isUnknown: true);
26442645

26452646
@override
26462647
int get hashCode {
@@ -2695,7 +2696,14 @@ class MapState extends InstanceState {
26952696
if (isUnknown || rightOperand.isUnknown) {
26962697
return BoolState.UNKNOWN_VALUE;
26972698
}
2698-
return BoolState.from(this == rightOperand);
2699+
if (rightOperand is! MapState) {
2700+
return BoolState.FALSE_STATE;
2701+
}
2702+
return BoolState.from(typeSystem.normalize(_keyType) ==
2703+
typeSystem.normalize(rightOperand._keyType) &&
2704+
typeSystem.normalize(_valueType) ==
2705+
typeSystem.normalize(rightOperand._valueType) &&
2706+
this == rightOperand);
26992707
}
27002708

27012709
@override
@@ -2913,8 +2921,7 @@ class RecordState extends InstanceState {
29132921

29142922
/// The state of an object representing a set.
29152923
class SetState extends InstanceState {
2916-
/// A state that represents a set whose value is not known.
2917-
static SetState UNKNOWN = SetState({}, isUnknown: true);
2924+
final DartType _elementType;
29182925

29192926
/// The elements of the set.
29202927
final Set<DartObjectImpl> elements;
@@ -2924,7 +2931,16 @@ class SetState extends InstanceState {
29242931

29252932
/// Initializes a newly created state to represent a set with the given
29262933
/// [elements].
2927-
SetState(this.elements, {bool isUnknown = false}) : _isUnknown = isUnknown;
2934+
SetState({
2935+
required DartType elementType,
2936+
required this.elements,
2937+
bool isUnknown = false,
2938+
}) : _elementType = elementType.extensionTypeErasure,
2939+
_isUnknown = isUnknown;
2940+
2941+
/// Creates a state that represents a list whose value is not known.
2942+
factory SetState.unknown(DartType elementType) =>
2943+
SetState(elementType: elementType, elements: {}, isUnknown: true);
29282944

29292945
@override
29302946
int get hashCode {
@@ -2978,7 +2994,12 @@ class SetState extends InstanceState {
29782994
if (isUnknown || rightOperand.isUnknown) {
29792995
return BoolState.UNKNOWN_VALUE;
29802996
}
2981-
return BoolState.from(this == rightOperand);
2997+
if (rightOperand is! SetState) {
2998+
return BoolState.FALSE_STATE;
2999+
}
3000+
return BoolState.from(typeSystem.normalize(_elementType) ==
3001+
typeSystem.normalize(rightOperand._elementType) &&
3002+
this == rightOperand);
29823003
}
29833004

29843005
@override

0 commit comments

Comments
 (0)