Skip to content

Commit 991f877

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Support superscope search in late initializer
From #43156 Closes #43137 Change-Id: I1ab972b93ee1d7b957c48d4097ff71fc1f1c5453 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/159842 Reviewed-by: Dmitry Stefantsov <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent 9ad6149 commit 991f877

15 files changed

+264
-37
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2069,7 +2069,8 @@ class BodyBuilder extends ScopeListener<JumpTarget>
20692069
Name n = new Name(name, libraryBuilder.nameOrigin);
20702070
if (!isQualified && isDeclarationInstanceContext) {
20712071
assert(declaration == null);
2072-
if (constantContext != ConstantContext.none || member.isField) {
2072+
if (constantContext != ConstantContext.none ||
2073+
(inFieldInitializer && !inLateFieldInitializer) && !inInitializer) {
20732074
return new UnresolvedNameGenerator(this, token, n);
20742075
}
20752076
if (extensionThis != null) {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ class _ImplicitFieldTypeRoot extends ImplicitFieldType {
140140
bodyBuilder.constantContext = fieldBuilder.isConst
141141
? ConstantContext.inferred
142142
: ConstantContext.none;
143+
bodyBuilder.inFieldInitializer = true;
144+
bodyBuilder.inLateFieldInitializer = fieldBuilder.isLate;
143145
Expression initializer =
144146
bodyBuilder.parseFieldInitializer(initializerToken);
145147
initializerToken = null;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright (c) 2020, 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 file.
4+
5+
class Class {
6+
var f = () => x; // error
7+
var x;
8+
}
9+
10+
main() {}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/general/field_initializer_capture_this.dart:6:17: Error: Can't access 'this' in a field initializer to read 'x'.
6+
// var f = () => x; // error
7+
// ^
8+
//
9+
import self as self;
10+
import "dart:core" as core;
11+
12+
class Class extends core::Object {
13+
field () →* dynamic f;
14+
field dynamic x;
15+
synthetic constructor •() → self::Class*
16+
;
17+
abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
18+
abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
19+
abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
20+
abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
21+
abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
22+
abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
23+
abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
24+
abstract member-signature method toString() → core::String*; -> core::Object::toString
25+
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
26+
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
27+
}
28+
static method main() → dynamic
29+
;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/general/field_initializer_capture_this.dart:6:17: Error: Can't access 'this' in a field initializer to read 'x'.
6+
// var f = () => x; // error
7+
// ^
8+
//
9+
import self as self;
10+
import "dart:core" as core;
11+
12+
class Class extends core::Object {
13+
field () →* dynamic f = () → dynamic => invalid-expression "pkg/front_end/testcases/general/field_initializer_capture_this.dart:6:17: Error: Can't access 'this' in a field initializer to read 'x'.
14+
var f = () => x; // error
15+
^";
16+
field dynamic x = null;
17+
synthetic constructor •() → self::Class*
18+
: super core::Object::•()
19+
;
20+
abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
21+
abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
22+
abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
23+
abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
24+
abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
25+
abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
26+
abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
27+
abstract member-signature method toString() → core::String*; -> core::Object::toString
28+
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
29+
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
30+
}
31+
static method main() → dynamic {}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/general/field_initializer_capture_this.dart:6:17: Error: Can't access 'this' in a field initializer to read 'x'.
6+
// var f = () => x; // error
7+
// ^
8+
//
9+
import self as self;
10+
import "dart:core" as core;
11+
12+
class Class extends core::Object {
13+
field () →* dynamic f = () → dynamic => invalid-expression "pkg/front_end/testcases/general/field_initializer_capture_this.dart:6:17: Error: Can't access 'this' in a field initializer to read 'x'.
14+
var f = () => x; // error
15+
^";
16+
field dynamic x = null;
17+
synthetic constructor •() → self::Class*
18+
: super core::Object::•()
19+
;
20+
abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
21+
abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
22+
abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
23+
abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
24+
abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
25+
abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
26+
abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
27+
abstract member-signature method toString() → core::String*; -> core::Object::toString
28+
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
29+
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
30+
}
31+
static method main() → dynamic {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Class {
2+
var f = () => x;
3+
var x;
4+
}
5+
6+
main() {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Class {
2+
var f = () => x;
3+
var x;
4+
}
5+
6+
main() {}

pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
class B {
6+
final int x;
7+
8+
B(this.x);
9+
}
10+
11+
class C extends B {
12+
late final y = x + 1;
13+
14+
C(int x) : super(x);
15+
16+
method() => x;
17+
}
18+
519
int? lateTopLevelField1Init;
620
int initLateTopLevelField1(int value) {
721
return lateTopLevelField1Init = value;
@@ -97,6 +111,7 @@ main() {
97111
expect(87, Extension.lateExtensionField1Init);
98112

99113
Extension.staticMethod();
114+
expect(2, C(1).y);
100115
}
101116

102117
expect(expected, actual) {

pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@ library /*isNonNullableByDefault*/;
22
import self as self;
33
import "dart:core" as core;
44

5+
class B extends core::Object {
6+
final field core::int x;
7+
constructor •(core::int x) → self::B
8+
;
9+
}
10+
class C extends self::B {
11+
field core::int? _#C#y;
12+
field core::bool _#C#y#isSet;
13+
constructor •(core::int x) → self::C
14+
;
15+
get y() → core::int;
16+
method method() → dynamic
17+
;
18+
}
519
class Class<T extends core::Object? = dynamic> extends core::Object {
620
static field core::int? lateStaticField1Init;
721
static field core::int? _#lateStaticField1;

pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,23 @@ import self as self;
33
import "dart:core" as core;
44
import "dart:_internal" as _in;
55

6+
class B extends core::Object {
7+
final field core::int x;
8+
constructor •(core::int x) → self::B
9+
: self::B::x = x, super core::Object::•()
10+
;
11+
}
12+
class C extends self::B {
13+
field core::int? _#C#y = null;
14+
field core::bool _#C#y#isSet = false;
15+
constructor •(core::int x) → self::C
16+
: super self::B::•(x)
17+
;
18+
get y() → core::int
19+
return let final core::int? #t1 = this.{self::C::_#C#y} in #t1.==(null) ?{core::int} let final core::int #t2 = this.{self::B::x}.{core::num::+}(1) in this.{self::C::_#C#y}.==(null) ?{core::int} this.{self::C::_#C#y} = #t2 : throw new _in::LateInitializationErrorImpl::•("Field 'y' has been assigned during initialization.") : #t1{core::int};
20+
method method() → dynamic
21+
return this.{self::B::x};
22+
}
623
class Class<T extends core::Object? = dynamic> extends core::Object {
724
static field core::int? lateStaticField1Init = null;
825
static field core::int? _#lateStaticField1 = null;
@@ -21,12 +38,12 @@ class Class<T extends core::Object? = dynamic> extends core::Object {
2138
return self::Class::lateStaticField1Init = value;
2239
}
2340
static get lateStaticField1() → core::int
24-
return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} let final core::int #t2 = self::Class::initLateStaticField1(87) in self::Class::_#lateStaticField1.==(null) ?{core::int} self::Class::_#lateStaticField1 = #t2 : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has been assigned during initialization.") : #t1{core::int};
41+
return let final core::int? #t3 = self::Class::_#lateStaticField1 in #t3.==(null) ?{core::int} let final core::int #t4 = self::Class::initLateStaticField1(87) in self::Class::_#lateStaticField1.==(null) ?{core::int} self::Class::_#lateStaticField1 = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has been assigned during initialization.") : #t3{core::int};
2542
static method initLateStaticField2(core::int value) → core::int {
2643
return self::Class::lateStaticField2Init = value;
2744
}
2845
static get lateStaticField2() → core::int
29-
return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} let final core::int #t4 = self::Class::initLateStaticField2(42) in self::Class::_#lateStaticField2.==(null) ?{core::int} self::Class::_#lateStaticField2 = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has been assigned during initialization.") : #t3{core::int};
46+
return let final core::int? #t5 = self::Class::_#lateStaticField2 in #t5.==(null) ?{core::int} let final core::int #t6 = self::Class::initLateStaticField2(42) in self::Class::_#lateStaticField2.==(null) ?{core::int} self::Class::_#lateStaticField2 = #t6 : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has been assigned during initialization.") : #t5{core::int};
3047
static method staticMethod() → dynamic {
3148
self::expect(null, self::Class::lateStaticField2Init);
3249
self::expect(42, self::Class::lateStaticField2);
@@ -36,19 +53,19 @@ class Class<T extends core::Object? = dynamic> extends core::Object {
3653
return this.{self::Class::lateInstanceFieldInit} = value;
3754
}
3855
get lateInstanceField() → core::int
39-
return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5.==(null) ?{core::int} let final core::int #t6 = this.{self::Class::initLateInstanceField}(16) in this.{self::Class::_#Class#lateInstanceField}.==(null) ?{core::int} this.{self::Class::_#Class#lateInstanceField} = #t6 : throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has been assigned during initialization.") : #t5{core::int};
56+
return let final core::int? #t7 = this.{self::Class::_#Class#lateInstanceField} in #t7.==(null) ?{core::int} let final core::int #t8 = this.{self::Class::initLateInstanceField}(16) in this.{self::Class::_#Class#lateInstanceField}.==(null) ?{core::int} this.{self::Class::_#Class#lateInstanceField} = #t8 : throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has been assigned during initialization.") : #t7{core::int};
4057
method initLateGenericField(generic-covariant-impl self::Class::T% value) → self::Class::T% {
4158
return this.{self::Class::lateGenericFieldInit} = value;
4259
}
4360
get lateGenericField() → self::Class::T% {
4461
if(!this.{self::Class::_#Class#lateGenericField#isSet}) {
45-
final self::Class::T% #t7 = this.{self::Class::initLateGenericField}(this.{self::Class::field});
62+
final self::Class::T% #t9 = this.{self::Class::initLateGenericField}(this.{self::Class::field});
4663
if(this.{self::Class::_#Class#lateGenericField#isSet})
4764
throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericField' has been assigned during initialization.");
48-
this.{self::Class::_#Class#lateGenericField} = #t7;
65+
this.{self::Class::_#Class#lateGenericField} = #t9;
4966
this.{self::Class::_#Class#lateGenericField#isSet} = true;
5067
}
51-
return let final self::Class::T? #t8 = this.{self::Class::_#Class#lateGenericField} in #t8{self::Class::T%};
68+
return let final self::Class::T? #t10 = this.{self::Class::_#Class#lateGenericField} in #t10{self::Class::T%};
5269
}
5370
method instanceMethod() → dynamic {
5471
self::expect(null, this.{self::Class::lateInstanceFieldInit});
@@ -80,17 +97,17 @@ static method initLateTopLevelField1(core::int value) → core::int {
8097
return self::lateTopLevelField1Init = value;
8198
}
8299
static get lateTopLevelField1() → core::int
83-
return let final core::int? #t9 = self::_#lateTopLevelField1 in #t9.==(null) ?{core::int} let final core::int #t10 = self::initLateTopLevelField1(123) in self::_#lateTopLevelField1.==(null) ?{core::int} self::_#lateTopLevelField1 = #t10 : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField1' has been assigned during initialization.") : #t9{core::int};
100+
return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11.==(null) ?{core::int} let final core::int #t12 = self::initLateTopLevelField1(123) in self::_#lateTopLevelField1.==(null) ?{core::int} self::_#lateTopLevelField1 = #t12 : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField1' has been assigned during initialization.") : #t11{core::int};
84101
static method Extension|initLateExtensionField1(core::int value) → core::int {
85102
return self::Extension|lateExtensionField1Init = value;
86103
}
87104
static get Extension|lateExtensionField1() → core::int
88-
return let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11.==(null) ?{core::int} let final core::int #t12 = self::Extension|initLateExtensionField1(87) in self::_#Extension|lateExtensionField1.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = #t12 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has been assigned during initialization.") : #t11{core::int};
105+
return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13.==(null) ?{core::int} let final core::int #t14 = self::Extension|initLateExtensionField1(87) in self::_#Extension|lateExtensionField1.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = #t14 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has been assigned during initialization.") : #t13{core::int};
89106
static method Extension|initLateExtensionField2(core::int value) → core::int {
90107
return self::Extension|lateExtensionField2Init = value;
91108
}
92109
static get Extension|lateExtensionField2() → core::int
93-
return let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13.==(null) ?{core::int} let final core::int #t14 = self::Extension|initLateExtensionField2(42) in self::_#Extension|lateExtensionField2.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = #t14 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has been assigned during initialization.") : #t13{core::int};
110+
return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15.==(null) ?{core::int} let final core::int #t16 = self::Extension|initLateExtensionField2(42) in self::_#Extension|lateExtensionField2.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has been assigned during initialization.") : #t15{core::int};
94111
static method Extension|staticMethod() → dynamic {
95112
self::expect(null, self::Extension|lateExtensionField2Init);
96113
self::expect(42, self::Extension|lateExtensionField2);
@@ -109,6 +126,7 @@ static method main() → dynamic {
109126
self::expect(87, self::Extension|lateExtensionField1);
110127
self::expect(87, self::Extension|lateExtensionField1Init);
111128
self::Extension|staticMethod();
129+
self::expect(2, new self::C::•(1).{self::C::y});
112130
}
113131
static method expect(dynamic expected, dynamic actual) → dynamic {
114132
if(!expected.{core::Object::==}(actual))

0 commit comments

Comments
 (0)