Skip to content

Commit 9cce31c

Browse files
scheglovCommit Queue
authored andcommitted
Fine. Make ClassItem subtype lists nullable.
Class subtype metadata is now optional rather than always present. `ClassItem.allSubtypes` and `ClassItem.directSubtypesOfSealed` are changed to `ManifestItemIdList?` so we can distinguish “not recorded / not applicable” from “recorded but empty”. This reduces bundle size and prevents spurious requirement mismatches when these values weren’t requested. Key changes: - Switch `ClassItem.allSubtypes` and `directSubtypesOfSealed` to nullable; update binary read/write to use optional encodings. - Only populate `allSubtypes` when `ClassElementImpl.allSubtypes` is non-null; only populate `directSubtypesOfSealed` for sealed classes. - Extend requirement tracking with `allSubtypesRequested`/`directSubtypesOfSealedRequested` flags and compare values only when requested. Mismatch types now carry nullable expected/actual lists. - Update hash computation to include optional lists via `addOptionalIdList`. - Adjust printers to emit these fields only when meaningful; print `<null>` when a requested value is absent. - Bump `AnalysisDriver.DATA_VERSION` to 577 to reflect the format change. - Refresh tests and expected outputs to the new semantics. This clarifies intent (requested vs. empty), avoids false positives in requirements checking, and slightly shrinks stored manifests. Change-Id: I21ba890d63575e7bc5498d08e894580b662283f6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/455340 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
1 parent e417270 commit 9cce31c

File tree

7 files changed

+136
-50
lines changed

7 files changed

+136
-50
lines changed

pkg/analyzer/lib/src/dart/analysis/driver.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ testFineAfterLibraryAnalyzerHook;
107107
// TODO(scheglov): Clean up the list of implicitly analyzed files.
108108
class AnalysisDriver {
109109
/// The version of data format, should be incremented on every format change.
110-
static const int DATA_VERSION = 575;
110+
static const int DATA_VERSION = 577;
111111

112112
/// The number of exception contexts allowed to write. Once this field is
113113
/// zero, we stop writing any new exception contexts in this process.

pkg/analyzer/lib/src/fine/library_manifest.dart

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,15 @@ class LibraryManifestBuilder {
10161016
builder.addList(idList.ids, addId);
10171017
}
10181018

1019+
void addOptionalIdList(ManifestItemIdList? idList) {
1020+
if (idList != null) {
1021+
builder.addBool(true);
1022+
addIdList(idList);
1023+
} else {
1024+
builder.addBool(false);
1025+
}
1026+
}
1027+
10191028
void addVersion(Version? version) {
10201029
if (version != null) {
10211030
builder.addBool(true);
@@ -1079,8 +1088,8 @@ class LibraryManifestBuilder {
10791088
builder.addBool(item.hasNonFinalField);
10801089
addId(item.interface.id);
10811090
if (item is ClassItem) {
1082-
addIdList(item.allSubtypes);
1083-
addIdList(item.directSubtypesOfSealed);
1091+
addOptionalIdList(item.allSubtypes);
1092+
addOptionalIdList(item.directSubtypesOfSealed);
10841093
}
10851094
}
10861095
}
@@ -1112,12 +1121,14 @@ class LibraryManifestBuilder {
11121121
var classItem = declaredItems[classElement];
11131122
if (classItem != null) {
11141123
classItem as ClassItem;
1115-
var ids = (classElement.allSubtypes ?? [])
1116-
.map((type) => declaredItems[type.element])
1117-
.whereType<InterfaceItem>()
1118-
.map((item) => item.id)
1119-
.sorted();
1120-
classItem.allSubtypes = ManifestItemIdList(ids);
1124+
if (classElement.allSubtypes case var allSubtypes?) {
1125+
var ids = allSubtypes
1126+
.map((type) => declaredItems[type.element])
1127+
.whereType<InterfaceItem>()
1128+
.map((item) => item.id)
1129+
.sorted();
1130+
classItem.allSubtypes = ManifestItemIdList(ids);
1131+
}
11211132
}
11221133
}
11231134
}

pkg/analyzer/lib/src/fine/manifest_item.dart

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ import 'package:pub_semver/pub_semver.dart';
2020

2121
class ClassItem extends InterfaceItem<ClassElementImpl> {
2222
/// See [ClassElementImpl.allSubtypes] for details.
23-
ManifestItemIdList allSubtypes;
23+
ManifestItemIdList? allSubtypes;
2424

2525
/// See [ClassElementImpl.directSubtypesOfSealed] for details.
26-
/// If the class is not sealed, then empty.
27-
ManifestItemIdList directSubtypesOfSealed;
26+
/// If the class is not sealed, then `null`.
27+
ManifestItemIdList? directSubtypesOfSealed;
2828

2929
ClassItem({
3030
required super.id,
@@ -70,8 +70,8 @@ class ClassItem extends InterfaceItem<ClassElementImpl> {
7070
mixins: element.mixins.encode(context),
7171
interfaces: element.interfaces.encode(context),
7272
interface: ManifestInterface.empty(),
73-
allSubtypes: ManifestItemIdList([]),
74-
directSubtypesOfSealed: ManifestItemIdList([]),
73+
allSubtypes: null,
74+
directSubtypesOfSealed: null,
7575
);
7676
});
7777
}
@@ -94,8 +94,8 @@ class ClassItem extends InterfaceItem<ClassElementImpl> {
9494
mixins: ManifestType.readList(reader),
9595
interfaces: ManifestType.readList(reader),
9696
interface: ManifestInterface.read(reader),
97-
allSubtypes: ManifestItemIdList.read(reader),
98-
directSubtypesOfSealed: ManifestItemIdList.read(reader),
97+
allSubtypes: ManifestItemIdList.readOptional(reader),
98+
directSubtypesOfSealed: ManifestItemIdList.readOptional(reader),
9999
);
100100
}
101101

@@ -117,8 +117,8 @@ class ClassItem extends InterfaceItem<ClassElementImpl> {
117117
@override
118118
void write(BinaryWriter writer) {
119119
super.write(writer);
120-
allSubtypes.write(writer);
121-
directSubtypesOfSealed.write(writer);
120+
allSubtypes.writeOptional(writer);
121+
directSubtypesOfSealed.writeOptional(writer);
122122
}
123123
}
124124

pkg/analyzer/lib/src/fine/requirement_failure.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ class InterfaceChildrenIdsMismatch extends RequirementFailure {
188188
final Uri libraryUri;
189189
final LookupName interfaceName;
190190
final String childrenPropertyName;
191-
final ManifestItemIdList expectedIds;
192-
final ManifestItemIdList actualIds;
191+
final ManifestItemIdList? expectedIds;
192+
final ManifestItemIdList? actualIds;
193193

194194
InterfaceChildrenIdsMismatch({
195195
required this.libraryUri,

pkg/analyzer/lib/src/fine/requirements.dart

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,16 @@ class InterfaceItemRequirements {
318318
final Map<LookupName, ManifestItemId?> implementedMethods;
319319
final Map<int, Map<LookupName, ManifestItemId?>> superMethods;
320320

321-
/// Set if [ClassElementImpl.allSubtypes] was invoked.
321+
/// Whether [ClassElementImpl.allSubtypes] was requested.
322+
bool allSubtypesRequested;
323+
324+
/// The recorded value of [ClassItem.allSubtypes].
322325
ManifestItemIdList? allSubtypes;
323326

324-
/// Set if [ClassElementImpl.directSubtypesOfSealed] was invoked.
327+
/// Whether [ClassElementImpl.directSubtypesOfSealed] was requested.
328+
bool directSubtypesOfSealedRequested;
329+
330+
/// The recorded value of [ClassItem.directSubtypesOfSealed].
325331
ManifestItemIdList? directSubtypesOfSealed;
326332

327333
InterfaceItemRequirements({
@@ -332,7 +338,9 @@ class InterfaceItemRequirements {
332338
required this.methods,
333339
required this.implementedMethods,
334340
required this.superMethods,
341+
required this.allSubtypesRequested,
335342
required this.allSubtypes,
343+
required this.directSubtypesOfSealedRequested,
336344
required this.directSubtypesOfSealed,
337345
});
338346

@@ -345,7 +353,9 @@ class InterfaceItemRequirements {
345353
methods: {},
346354
implementedMethods: {},
347355
superMethods: {},
356+
allSubtypesRequested: false,
348357
allSubtypes: null,
358+
directSubtypesOfSealedRequested: false,
349359
directSubtypesOfSealed: null,
350360
);
351361
}
@@ -362,7 +372,9 @@ class InterfaceItemRequirements {
362372
readKey: () => reader.readInt64(),
363373
readValue: () => reader.readNameToOptionalIdMap(),
364374
),
375+
allSubtypesRequested: reader.readBool(),
365376
allSubtypes: ManifestItemIdList.readOptional(reader),
377+
directSubtypesOfSealedRequested: reader.readBool(),
366378
directSubtypesOfSealed: ManifestItemIdList.readOptional(reader),
367379
);
368380
}
@@ -379,7 +391,9 @@ class InterfaceItemRequirements {
379391
writeKey: (index) => writer.writeInt64(index),
380392
writeValue: (map) => writer.writeNameToIdMap(map),
381393
);
394+
writer.writeBool(allSubtypesRequested);
382395
allSubtypes.writeOptional(writer);
396+
writer.writeBool(directSubtypesOfSealedRequested);
383397
directSubtypesOfSealed.writeOptional(writer);
384398
}
385399
}
@@ -1566,8 +1580,9 @@ class RequirementsManifest {
15661580
}
15671581
}
15681582

1569-
if (interfaceRequirements.allSubtypes case var required?) {
1583+
if (interfaceRequirements.allSubtypesRequested) {
15701584
interfaceItem as ClassItem;
1585+
var required = interfaceRequirements.allSubtypes;
15711586
var actualIds = interfaceItem.allSubtypes;
15721587
if (required != actualIds) {
15731588
return InterfaceChildrenIdsMismatch(
@@ -1580,8 +1595,9 @@ class RequirementsManifest {
15801595
}
15811596
}
15821597

1583-
if (interfaceRequirements.directSubtypesOfSealed case var required?) {
1598+
if (interfaceRequirements.directSubtypesOfSealedRequested) {
15841599
interfaceItem as ClassItem;
1600+
var required = interfaceRequirements.directSubtypesOfSealed;
15851601
var actualIds = interfaceItem.directSubtypesOfSealed;
15861602
if (required != actualIds) {
15871603
return InterfaceChildrenIdsMismatch(
@@ -1643,7 +1659,8 @@ class RequirementsManifest {
16431659
var item = itemRequirements.item as ClassItem;
16441660
var requirements = itemRequirements.requirements;
16451661

1646-
requirements.allSubtypes ??= item.allSubtypes;
1662+
requirements.allSubtypesRequested = true;
1663+
requirements.allSubtypes = item.allSubtypes;
16471664
}
16481665

16491666
void record_classElement_directSubtypesOfSealed({
@@ -1661,7 +1678,8 @@ class RequirementsManifest {
16611678
var item = itemRequirements.item as ClassItem;
16621679
var requirements = itemRequirements.requirements;
16631680

1664-
requirements.directSubtypesOfSealed ??= item.directSubtypesOfSealed;
1681+
requirements.directSubtypesOfSealedRequested = true;
1682+
requirements.directSubtypesOfSealed = item.directSubtypesOfSealed;
16651683
}
16661684

16671685
void record_fieldElement_getter({

pkg/analyzer/test/src/dart/analysis/driver_test.dart

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6163,10 +6163,10 @@ void f(A a) {
61636163
B: false
61646164
interfaces
61656165
A
6166-
allSubtypes: []
6166+
allSubtypes: <null>
61676167
directSubtypesOfSealed: #M2
61686168
B
6169-
allSubtypes: []
6169+
allSubtypes: <null>
61706170
[status] idle
61716171
[future] getErrors T1
61726172
ErrorsResult #0
@@ -6227,10 +6227,10 @@ class C extends A {}
62276227
B: false
62286228
interfaces
62296229
A
6230-
allSubtypes: []
6230+
allSubtypes: <null>
62316231
directSubtypesOfSealed: #M2 #M8
62326232
B
6233-
allSubtypes: []
6233+
allSubtypes: <null>
62346234
[status] idle
62356235
[future] getErrors T2
62366236
ErrorsResult #1
@@ -56054,6 +56054,7 @@ class extends A {}
5605456054
A: #M0
5605556055
flags: isFinal
5605656056
supertype: Object @ dart:core
56057+
allSubtypes: []
5605756058
interface: #M1
5605856059
exportMapId: #M2
5605956060
exportMap
@@ -56216,6 +56217,7 @@ class C {}
5621656217
B: #M1
5621756218
flags: isFinal
5621856219
supertype: A @ package:test/test.dart
56220+
allSubtypes: []
5621956221
interface: #M3
5622056222
C: #M4
5622156223
supertype: Object @ dart:core
@@ -56254,6 +56256,7 @@ final class D extends B {}
5625456256
D: #M7
5625556257
flags: isFinal
5625656258
supertype: B @ package:test/test.dart
56259+
allSubtypes: []
5625756260
interface: #M8
5625856261
exportMapId: #M9
5625956262
exportMap
@@ -68326,6 +68329,7 @@ class D {}
6832668329
}
6832768330

6832868331
test_manifest_class_modifier_isFinal() async {
68332+
configuration.withElementManifests = true;
6832968333
await _runLibraryManifestScenario(
6833068334
initialCode: r'''
6833168335
class A {}
@@ -68340,12 +68344,20 @@ final class D {}
6834068344
hashForRequirements: #H0
6834168345
declaredClasses
6834268346
A: #M0
68347+
supertype: Object @ dart:core
6834368348
interface: #M1
6834468349
B: #M2
68350+
flags: isFinal
68351+
supertype: Object @ dart:core
68352+
allSubtypes: []
6834568353
interface: #M3
6834668354
C: #M4
68355+
supertype: Object @ dart:core
6834768356
interface: #M5
6834868357
D: #M6
68358+
flags: isFinal
68359+
supertype: Object @ dart:core
68360+
allSubtypes: []
6834968361
interface: #M7
6835068362
exportMapId: #M8
6835168363
exportMap
@@ -68366,12 +68378,20 @@ class D {}
6836668378
hashForRequirements: #H1
6836768379
declaredClasses
6836868380
A: #M0
68381+
supertype: Object @ dart:core
6836968382
interface: #M1
6837068383
B: #M2
68384+
flags: isFinal
68385+
supertype: Object @ dart:core
68386+
allSubtypes: []
6837168387
interface: #M3
6837268388
C: #M9
68389+
flags: isFinal
68390+
supertype: Object @ dart:core
68391+
allSubtypes: []
6837368392
interface: #M10
6837468393
D: #M11
68394+
supertype: Object @ dart:core
6837568395
interface: #M12
6837668396
exportMapId: #M13
6837768397
exportMap
@@ -68568,6 +68588,7 @@ class D {}
6856868588
}
6856968589

6857068590
test_manifest_class_modifier_isSealed() async {
68591+
configuration.withElementManifests = true;
6857168592
await _runLibraryManifestScenario(
6857268593
initialCode: r'''
6857368594
class A {}
@@ -68582,12 +68603,22 @@ sealed class D {}
6858268603
hashForRequirements: #H0
6858368604
declaredClasses
6858468605
A: #M0
68606+
supertype: Object @ dart:core
6858568607
interface: #M1
6858668608
B: #M2
68609+
flags: isAbstract isSealed
68610+
supertype: Object @ dart:core
68611+
allSubtypes: []
68612+
directSubtypesOfSealed: []
6858768613
interface: #M3
6858868614
C: #M4
68615+
supertype: Object @ dart:core
6858968616
interface: #M5
6859068617
D: #M6
68618+
flags: isAbstract isSealed
68619+
supertype: Object @ dart:core
68620+
allSubtypes: []
68621+
directSubtypesOfSealed: []
6859168622
interface: #M7
6859268623
exportMapId: #M8
6859368624
exportMap
@@ -68608,12 +68639,22 @@ class D {}
6860868639
hashForRequirements: #H1
6860968640
declaredClasses
6861068641
A: #M0
68642+
supertype: Object @ dart:core
6861168643
interface: #M1
6861268644
B: #M2
68645+
flags: isAbstract isSealed
68646+
supertype: Object @ dart:core
68647+
allSubtypes: []
68648+
directSubtypesOfSealed: []
6861368649
interface: #M3
6861468650
C: #M9
68651+
flags: isAbstract isSealed
68652+
supertype: Object @ dart:core
68653+
allSubtypes: []
68654+
directSubtypesOfSealed: []
6861568655
interface: #M10
6861668656
D: #M11
68657+
supertype: Object @ dart:core
6861768658
interface: #M12
6861868659
exportMapId: #M13
6861968660
exportMap

0 commit comments

Comments
 (0)