Skip to content

Commit 7964e40

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Ensure that source/dill export scopes match during incremental compilation
This fix the breakage found in https://dart-review.googlesource.com/c/sdk/+/166603/4 trying to update to the most recent package:collection Change-Id: Ie71e97cc92d39dd121825447edf8460858c5156e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166846 Commit-Queue: Johnni Winther <[email protected]> Reviewed-by: Jens Johansen <[email protected]>
1 parent 666dad0 commit 7964e40

7 files changed

+355
-4
lines changed

pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ class DillLibraryBuilder extends LibraryBuilderImpl {
187187
}
188188

189189
void addMember(Member member) {
190+
if (member.isExtensionMember) {
191+
return null;
192+
}
190193
String name = member.name.text;
191194
if (name == "_exports#") {
192195
Field field = member;
@@ -210,6 +213,7 @@ class DillLibraryBuilder extends LibraryBuilderImpl {
210213
@override
211214
Builder addBuilder(String name, Builder declaration, int charOffset) {
212215
if (name == null || name.isEmpty) return null;
216+
213217
bool isSetter = declaration.isSetter;
214218
if (isSetter) {
215219
scopeBuilder.addSetter(name, declaration);
@@ -219,7 +223,7 @@ class DillLibraryBuilder extends LibraryBuilderImpl {
219223
if (declaration.isExtension) {
220224
scopeBuilder.addExtension(declaration);
221225
}
222-
if (!name.startsWith("_")) {
226+
if (!name.startsWith("_") && !name.contains('#')) {
223227
if (isSetter) {
224228
exportScopeBuilder.addSetter(name, declaration);
225229
} else {

pkg/front_end/lib/src/fasta/incremental_compiler.dart

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ import 'builder/builder.dart' show Builder;
6060

6161
import 'builder/class_builder.dart' show ClassBuilder;
6262

63+
import 'builder/field_builder.dart' show FieldBuilder;
64+
6365
import 'builder/library_builder.dart' show LibraryBuilder;
6466

6567
import 'builder/name_iterator.dart' show NameIterator;
@@ -388,6 +390,8 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
388390
// We suppress finalization errors because they have already been
389391
// reported.
390392
await dillLoadedData.buildOutlines(suppressFinalizationErrors: true);
393+
assert(_checkEquivalentScopes(
394+
userCode.loader.builders, dillLoadedData.loader.builders));
391395

392396
if (experimentalInvalidation != null) {
393397
/// If doing experimental invalidation that means that some of the old
@@ -432,6 +436,80 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
432436
return newDillLibraryBuilders;
433437
}
434438

439+
bool _checkEquivalentScopes(Map<Uri, LibraryBuilder> sourceLibraries,
440+
Map<Uri, LibraryBuilder> dillLibraries) {
441+
sourceLibraries.forEach((Uri uri, LibraryBuilder sourceLibraryBuilder) {
442+
if (sourceLibraryBuilder is SourceLibraryBuilder) {
443+
DillLibraryBuilder dillLibraryBuilder = dillLibraries[uri];
444+
assert(
445+
_hasEquivalentScopes(sourceLibraryBuilder, dillLibraryBuilder) ==
446+
null,
447+
_hasEquivalentScopes(sourceLibraryBuilder, dillLibraryBuilder));
448+
}
449+
});
450+
return true;
451+
}
452+
453+
String _hasEquivalentScopes(SourceLibraryBuilder sourceLibraryBuilder,
454+
DillLibraryBuilder dillLibraryBuilder) {
455+
bool isEquivalent = true;
456+
StringBuffer sb = new StringBuffer();
457+
sb.writeln('Mismatch on ${sourceLibraryBuilder.importUri}:');
458+
sourceLibraryBuilder.exportScope
459+
.forEachLocalMember((String name, Builder sourceBuilder) {
460+
Builder dillBuilder =
461+
dillLibraryBuilder.exportScope.lookupLocalMember(name, setter: false);
462+
if (dillBuilder == null) {
463+
if ((name == 'dynamic' || name == 'Never') &&
464+
sourceLibraryBuilder.importUri == Uri.parse('dart:core')) {
465+
// The source library builder for dart:core has synthetically
466+
// injected builders for `dynamic` and `Never` which do not have
467+
// corresponding classes in the AST.
468+
return;
469+
}
470+
sb.writeln('No dill builder for ${name}: $sourceBuilder');
471+
isEquivalent = false;
472+
}
473+
});
474+
dillLibraryBuilder.exportScope
475+
.forEachLocalMember((String name, Builder dillBuilder) {
476+
Builder sourceBuilder = sourceLibraryBuilder.exportScope
477+
.lookupLocalMember(name, setter: false);
478+
if (sourceBuilder == null) {
479+
sb.writeln('No source builder for ${name}: $dillBuilder');
480+
isEquivalent = false;
481+
}
482+
});
483+
sourceLibraryBuilder.exportScope
484+
.forEachLocalSetter((String name, Builder sourceBuilder) {
485+
Builder dillBuilder =
486+
dillLibraryBuilder.exportScope.lookupLocalMember(name, setter: true);
487+
if (dillBuilder == null) {
488+
sb.writeln('No dill builder for ${name}=: $sourceBuilder');
489+
isEquivalent = false;
490+
}
491+
});
492+
dillLibraryBuilder.exportScope
493+
.forEachLocalSetter((String name, Builder dillBuilder) {
494+
Builder sourceBuilder = sourceLibraryBuilder.exportScope
495+
.lookupLocalMember(name, setter: true);
496+
if (sourceBuilder == null) {
497+
sourceBuilder = sourceLibraryBuilder.exportScope
498+
.lookupLocalMember(name, setter: false);
499+
if (sourceBuilder is FieldBuilder && sourceBuilder.isAssignable) {
500+
// Assignable fields can be lowered into a getter and setter.
501+
return;
502+
}
503+
sb.writeln('No source builder for ${name}=: $dillBuilder');
504+
isEquivalent = false;
505+
}
506+
});
507+
if (isEquivalent) {
508+
return null;
509+
}
510+
return sb.toString();
511+
}
512+
435513
/// Compute which libraries to output and which (previous) errors/warnings we
436514
/// have to reissue. In the process do some cleanup too.
437515
List<Library> calculateOutputLibrariesAndIssueLibraryProblems(

pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_34.yaml.world.4.expect

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
main = <No Member>;
22
library from "org-dartlang-test:///lib1.dart" as lib1 {
3-
additionalExports = (main::Extension|get#method,
4-
main::Extension|method,
5-
main::main,
3+
additionalExports = (main::main,
64
main::Class,
75
main::Extension)
86

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
# for details. All rights reserved. Use of this source code is governed by a
3+
# BSD-style license that can be found in the LICENSE.md file.
4+
5+
# Compile an application, change a file, but don't change the outline.
6+
# Mixin something from the same file.
7+
8+
type: newworld
9+
worlds:
10+
- entry: main.dart
11+
experiments: alternative-invalidation-strategy
12+
sources:
13+
lib1.dart: |
14+
import 'main.dart';
15+
extension Extension1 on A {
16+
baz() => 42;
17+
}
18+
lib2.dart: |
19+
import 'main.dart';
20+
import 'lib1.dart';
21+
export 'main.dart';
22+
export 'lib1.dart';
23+
method(A a) {
24+
a.baz();
25+
a.boz();
26+
}
27+
main.dart: |
28+
import 'lib1.dart';
29+
import 'lib2.dart';
30+
class A {
31+
foo() {}
32+
}
33+
main() {
34+
method(new A());
35+
}
36+
extension Extension2 on A {
37+
boz() => 87;
38+
}
39+
expectedLibraryCount: 3
40+
- entry: main.dart
41+
experiments: alternative-invalidation-strategy
42+
worldType: updated
43+
expectInitializeFromDill: false
44+
invalidate:
45+
- lib2.dart
46+
sources:
47+
lib2.dart: |
48+
import 'main.dart';
49+
import 'lib1.dart';
50+
export 'main.dart';
51+
export 'lib1.dart';
52+
method(A a) {
53+
a.baz();
54+
a.boz();
55+
a.baz();
56+
}
57+
expectedLibraryCount: 3
58+
expectsRebuildBodiesOnly: true
59+
- entry: main.dart
60+
experiments: alternative-invalidation-strategy
61+
worldType: updated
62+
expectInitializeFromDill: false
63+
invalidate:
64+
- main.dart
65+
sources:
66+
main.dart: |
67+
import 'lib1.dart';
68+
import 'lib2.dart';
69+
class A {
70+
foo() {}
71+
}
72+
main() {
73+
method(new A());
74+
}
75+
extension Extension2 on A {
76+
boz() => 123;
77+
}
78+
expectedLibraryCount: 3
79+
expectsRebuildBodiesOnly: true
80+
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
main = <No Member>;
2+
library from "org-dartlang-test:///lib1.dart" as lib1 {
3+
4+
import "org-dartlang-test:///main.dart";
5+
6+
extension Extension1 on main::A* {
7+
method baz = lib1::Extension1|baz;
8+
tearoff baz = lib1::Extension1|get#baz;
9+
}
10+
static method Extension1|baz(final main::A* #this) → dynamic
11+
return 42;
12+
static method Extension1|get#baz(final main::A* #this) → () →* dynamic
13+
return () → dynamic => lib1::Extension1|baz(#this);
14+
}
15+
library from "org-dartlang-test:///lib2.dart" as lib2 {
16+
additionalExports = (lib1::Extension1,
17+
main::main,
18+
main::A,
19+
main::Extension2)
20+
21+
import "org-dartlang-test:///main.dart";
22+
import "org-dartlang-test:///lib1.dart";
23+
export "org-dartlang-test:///main.dart";
24+
export "org-dartlang-test:///lib1.dart";
25+
26+
static method method(main::A* a) → dynamic {
27+
lib1::Extension1|baz(a);
28+
main::Extension2|boz(a);
29+
}
30+
}
31+
library from "org-dartlang-test:///main.dart" as main {
32+
33+
import "org-dartlang-test:///lib1.dart";
34+
import "org-dartlang-test:///lib2.dart";
35+
36+
class A extends dart.core::Object {
37+
synthetic constructor •() → main::A*
38+
: super dart.core::Object::•()
39+
;
40+
method foo() → dynamic {}
41+
abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
42+
abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
43+
abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
44+
abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
45+
abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
46+
abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
47+
abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
48+
abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
49+
abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
50+
abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
51+
}
52+
extension Extension2 on main::A* {
53+
method boz = main::Extension2|boz;
54+
tearoff boz = main::Extension2|get#boz;
55+
}
56+
static method main() → dynamic {
57+
lib2::method(new main::A::•());
58+
}
59+
static method Extension2|boz(final main::A* #this) → dynamic
60+
return 87;
61+
static method Extension2|get#boz(final main::A* #this) → () →* dynamic
62+
return () → dynamic => main::Extension2|boz(#this);
63+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
main = <No Member>;
2+
library from "org-dartlang-test:///lib1.dart" as lib1 {
3+
4+
import "org-dartlang-test:///main.dart";
5+
6+
extension Extension1 on main::A* {
7+
method baz = lib1::Extension1|baz;
8+
tearoff baz = lib1::Extension1|get#baz;
9+
}
10+
static method Extension1|baz(final main::A* #this) → dynamic
11+
return 42;
12+
static method Extension1|get#baz(final main::A* #this) → () →* dynamic
13+
return () → dynamic => lib1::Extension1|baz(#this);
14+
}
15+
library from "org-dartlang-test:///lib2.dart" as lib2 {
16+
additionalExports = (lib1::Extension1,
17+
main::main,
18+
main::A,
19+
main::Extension2)
20+
21+
import "org-dartlang-test:///main.dart";
22+
import "org-dartlang-test:///lib1.dart";
23+
export "org-dartlang-test:///main.dart";
24+
export "org-dartlang-test:///lib1.dart";
25+
26+
static method method(main::A* a) → dynamic {
27+
lib1::Extension1|baz(a);
28+
main::Extension2|boz(a);
29+
lib1::Extension1|baz(a);
30+
}
31+
}
32+
library from "org-dartlang-test:///main.dart" as main {
33+
34+
import "org-dartlang-test:///lib1.dart";
35+
import "org-dartlang-test:///lib2.dart";
36+
37+
class A extends dart.core::Object {
38+
synthetic constructor •() → main::A*
39+
: super dart.core::Object::•()
40+
;
41+
method foo() → dynamic {}
42+
abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
43+
abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
44+
abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
45+
abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
46+
abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
47+
abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
48+
abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
49+
abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
50+
abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
51+
abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
52+
}
53+
extension Extension2 on main::A* {
54+
method boz = main::Extension2|boz;
55+
tearoff boz = main::Extension2|get#boz;
56+
}
57+
static method main() → dynamic {
58+
lib2::method(new main::A::•());
59+
}
60+
static method Extension2|boz(final main::A* #this) → dynamic
61+
return 87;
62+
static method Extension2|get#boz(final main::A* #this) → () →* dynamic
63+
return () → dynamic => main::Extension2|boz(#this);
64+
}

0 commit comments

Comments
 (0)