mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:01:42 +00:00
[cfe] Setup correct scope for builder outline expressions on extension fields
Closes https://github.com/dart-lang/sdk/issues/47345 Change-Id: I3a666fde4d6dd802e6101ccbd55dff11c0179fba Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215401 Reviewed-by: Jens Johansen <jensj@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
parent
fcd684e7d1
commit
b6b81ebad1
|
@ -426,8 +426,14 @@ class SourceFieldBuilder extends MemberBuilderImpl implements FieldBuilder {
|
|||
_fieldEncoding.completeSignature(coreTypes);
|
||||
|
||||
for (Annotatable annotatable in _fieldEncoding.annotatables) {
|
||||
MetadataBuilder.buildAnnotations(annotatable, metadata, library,
|
||||
classBuilder, this, fileUri, classBuilder?.scope ?? library.scope);
|
||||
MetadataBuilder.buildAnnotations(
|
||||
annotatable,
|
||||
metadata,
|
||||
library,
|
||||
declarationBuilder,
|
||||
this,
|
||||
fileUri,
|
||||
declarationBuilder?.scope ?? library.scope);
|
||||
}
|
||||
|
||||
// For modular compilation we need to include initializers of all const
|
||||
|
@ -439,10 +445,10 @@ class SourceFieldBuilder extends MemberBuilderImpl implements FieldBuilder {
|
|||
isClassMember &&
|
||||
classBuilder!.declaresConstConstructor)) &&
|
||||
_constInitializerToken != null) {
|
||||
Scope scope = classBuilder?.scope ?? library.scope;
|
||||
Scope scope = declarationBuilder?.scope ?? library.scope;
|
||||
BodyBuilder bodyBuilder = library.loader
|
||||
.createBodyBuilderForOutlineExpression(
|
||||
library, classBuilder, this, scope, fileUri);
|
||||
library, declarationBuilder, this, scope, fileUri);
|
||||
bodyBuilder.constantContext =
|
||||
isConst ? ConstantContext.inferred : ConstantContext.required;
|
||||
Expression initializer = bodyBuilder.typeInferrer.inferFieldInitializer(
|
||||
|
|
|
@ -207,6 +207,11 @@ abstract class MemberBuilderImpl extends ModifierBuilderImpl
|
|||
return buffer;
|
||||
}
|
||||
|
||||
/// The builder for the enclosing class or extension, if any.
|
||||
DeclarationBuilder? get declarationBuilder =>
|
||||
parent is DeclarationBuilder ? parent as DeclarationBuilder : null;
|
||||
|
||||
/// The builder for the enclosing class, if any.
|
||||
ClassBuilder? get classBuilder =>
|
||||
parent is ClassBuilder ? parent as ClassBuilder : null;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// @dart=2.9
|
||||
|
||||
class Class {
|
||||
@pragma('dart2js:noInline')
|
||||
instanceMethod() {}
|
||||
|
|
|
@ -43,9 +43,9 @@ static method main() → dynamic
|
|||
|
||||
|
||||
Extra constant evaluation status:
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:6:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:9:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:14:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:17:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:21:2 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:8:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:11:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:16:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:19:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
|
||||
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:23:2 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
|
||||
Extra constant evaluation: evaluated: 8, effectively constant: 5
|
||||
|
|
25
pkg/front_end/testcases/extensions/annotations_scope.dart
Normal file
25
pkg/front_end/testcases/extensions/annotations_scope.dart
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// Test that extension member annotations can access other extension static
|
||||
// members from the same extension by simple name.
|
||||
|
||||
extension E on int {
|
||||
@constField
|
||||
static const int constField = 1;
|
||||
|
||||
@constField2
|
||||
static const int constField1 = 2;
|
||||
|
||||
@constField1
|
||||
static const int constField2 = 3;
|
||||
|
||||
@constField
|
||||
static void staticMethod() {}
|
||||
|
||||
@constField
|
||||
void instanceMethod() {}
|
||||
}
|
||||
|
||||
main() {}
|
|
@ -0,0 +1,14 @@
|
|||
extension E on int {
|
||||
@constField
|
||||
static const int constField = 1;
|
||||
@constField2
|
||||
static const int constField1 = 2;
|
||||
@constField1
|
||||
static const int constField2 = 3;
|
||||
@constField
|
||||
static void staticMethod() {}
|
||||
@constField
|
||||
void instanceMethod() {}
|
||||
}
|
||||
|
||||
main() {}
|
|
@ -0,0 +1,14 @@
|
|||
extension E on int {
|
||||
@constField
|
||||
static const int constField = 1;
|
||||
@constField2
|
||||
static const int constField1 = 2;
|
||||
@constField1
|
||||
static const int constField2 = 3;
|
||||
@constField
|
||||
static void staticMethod() {}
|
||||
@constField
|
||||
void instanceMethod() {}
|
||||
}
|
||||
|
||||
main() {}
|
|
@ -0,0 +1,31 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
extension E on core::int {
|
||||
static field constField = self::E|constField;
|
||||
static field constField1 = self::E|constField1;
|
||||
static field constField2 = self::E|constField2;
|
||||
static method staticMethod = self::E|staticMethod;
|
||||
method instanceMethod = self::E|instanceMethod;
|
||||
tearoff instanceMethod = self::E|get#instanceMethod;
|
||||
}
|
||||
@#C1
|
||||
static const field core::int E|constField = #C1;
|
||||
@#C2
|
||||
static const field core::int E|constField1 = #C3;
|
||||
@#C3
|
||||
static const field core::int E|constField2 = #C2;
|
||||
@#C1
|
||||
static method E|staticMethod() → void {}
|
||||
@#C1
|
||||
static method E|instanceMethod(lowered final core::int #this) → void {}
|
||||
static method E|get#instanceMethod(lowered final core::int #this) → () → void
|
||||
return () → void => self::E|instanceMethod(#this);
|
||||
static method main() → dynamic {}
|
||||
|
||||
constants {
|
||||
#C1 = 1
|
||||
#C2 = 3
|
||||
#C3 = 2
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
extension E on core::int {
|
||||
static field constField = self::E|constField;
|
||||
static field constField1 = self::E|constField1;
|
||||
static field constField2 = self::E|constField2;
|
||||
static method staticMethod = self::E|staticMethod;
|
||||
method instanceMethod = self::E|instanceMethod;
|
||||
tearoff instanceMethod = self::E|get#instanceMethod;
|
||||
}
|
||||
@self::E|constField
|
||||
static const field core::int E|constField = 1;
|
||||
@self::E|constField2
|
||||
static const field core::int E|constField1 = 2;
|
||||
@self::E|constField1
|
||||
static const field core::int E|constField2 = 3;
|
||||
@self::E|constField
|
||||
static method E|staticMethod() → void
|
||||
;
|
||||
@self::E|constField
|
||||
static method E|instanceMethod(lowered final core::int #this) → void
|
||||
;
|
||||
static method E|get#instanceMethod(lowered final core::int #this) → () → void
|
||||
return () → void => self::E|instanceMethod(#this);
|
||||
static method main() → dynamic
|
||||
;
|
||||
|
||||
|
||||
Extra constant evaluation status:
|
||||
Evaluated: StaticGet @ org-dartlang-testcase:///annotations_scope.dart:18:4 -> IntConstant(1)
|
||||
Evaluated: StaticGet @ org-dartlang-testcase:///annotations_scope.dart:21:4 -> IntConstant(1)
|
||||
Evaluated: StaticGet @ org-dartlang-testcase:///annotations_scope.dart:9:4 -> IntConstant(1)
|
||||
Evaluated: StaticGet @ org-dartlang-testcase:///annotations_scope.dart:12:4 -> IntConstant(3)
|
||||
Evaluated: StaticGet @ org-dartlang-testcase:///annotations_scope.dart:15:4 -> IntConstant(2)
|
||||
Extra constant evaluation: evaluated: 8, effectively constant: 5
|
|
@ -0,0 +1,31 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
extension E on core::int {
|
||||
static field constField = self::E|constField;
|
||||
static field constField1 = self::E|constField1;
|
||||
static field constField2 = self::E|constField2;
|
||||
static method staticMethod = self::E|staticMethod;
|
||||
method instanceMethod = self::E|instanceMethod;
|
||||
tearoff instanceMethod = self::E|get#instanceMethod;
|
||||
}
|
||||
@#C1
|
||||
static const field core::int E|constField = #C1;
|
||||
@#C2
|
||||
static const field core::int E|constField1 = #C3;
|
||||
@#C3
|
||||
static const field core::int E|constField2 = #C2;
|
||||
@#C1
|
||||
static method E|staticMethod() → void {}
|
||||
@#C1
|
||||
static method E|instanceMethod(lowered final core::int #this) → void {}
|
||||
static method E|get#instanceMethod(lowered final core::int #this) → () → void
|
||||
return () → void => self::E|instanceMethod(#this);
|
||||
static method main() → dynamic {}
|
||||
|
||||
constants {
|
||||
#C1 = 1
|
||||
#C2 = 3
|
||||
#C3 = 2
|
||||
}
|
12
pkg/front_end/testcases/extensions/issue47345.dart
Normal file
12
pkg/front_end/testcases/extensions/issue47345.dart
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
void main() {}
|
||||
|
||||
class Foo {}
|
||||
|
||||
extension on Foo {
|
||||
static const bar = 1;
|
||||
static const doubleBar = bar * 2;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
void main() {}
|
||||
|
||||
class Foo {}
|
||||
|
||||
extension on Foo {
|
||||
static const bar = 1;
|
||||
static const doubleBar = bar * 2;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
class Foo {}
|
||||
|
||||
extension on Foo {
|
||||
static const bar = 1;
|
||||
static const doubleBar = bar * 2;
|
||||
}
|
||||
|
||||
void main() {}
|
|
@ -0,0 +1,21 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
class Foo extends core::Object {
|
||||
synthetic constructor •() → self::Foo
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
extension _extension#0 on self::Foo {
|
||||
static field bar = self::_extension#0|bar;
|
||||
static field doubleBar = self::_extension#0|doubleBar;
|
||||
}
|
||||
static const field core::int _extension#0|bar = #C1;
|
||||
static const field core::int _extension#0|doubleBar = #C2;
|
||||
static method main() → void {}
|
||||
|
||||
constants {
|
||||
#C1 = 1
|
||||
#C2 = 2
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
class Foo extends core::Object {
|
||||
synthetic constructor •() → self::Foo
|
||||
;
|
||||
}
|
||||
extension _extension#0 on self::Foo {
|
||||
static field bar = self::_extension#0|bar;
|
||||
static field doubleBar = self::_extension#0|doubleBar;
|
||||
}
|
||||
static const field core::int _extension#0|bar = 1;
|
||||
static const field core::int _extension#0|doubleBar = self::_extension#0|bar.{core::num::*}(2){(core::num) → core::int};
|
||||
static method main() → void
|
||||
;
|
||||
|
||||
|
||||
Extra constant evaluation status:
|
||||
Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue47345.dart:11:32 -> IntConstant(2)
|
||||
Extra constant evaluation: evaluated: 1, effectively constant: 1
|
|
@ -0,0 +1,21 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
class Foo extends core::Object {
|
||||
synthetic constructor •() → self::Foo
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
extension _extension#0 on self::Foo {
|
||||
static field bar = self::_extension#0|bar;
|
||||
static field doubleBar = self::_extension#0|doubleBar;
|
||||
}
|
||||
static const field core::int _extension#0|bar = #C1;
|
||||
static const field core::int _extension#0|doubleBar = #C2;
|
||||
static method main() → void {}
|
||||
|
||||
constants {
|
||||
#C1 = 1
|
||||
#C2 = 2
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// @dart=2.9
|
||||
|
||||
extension Test<T> on T {
|
||||
T Function(T) get test => (a) => this;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ library;
|
|||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/extensions/language_issue1182.dart:11:25: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'S Function(S)'.
|
||||
// pkg/front_end/testcases/extensions/language_issue1182.dart:13:25: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'S Function(S)'.
|
||||
// S Function(S) f = x.test;
|
||||
// ^
|
||||
//
|
||||
|
@ -14,7 +14,7 @@ class Foo<S extends core::num*> extends core::Object {
|
|||
: super core::Object::•()
|
||||
;
|
||||
method test1(covariant-by-class self::Foo::S* x) → void {
|
||||
(self::Foo::S*) →* self::Foo::S* f = invalid-expression "pkg/front_end/testcases/extensions/language_issue1182.dart:11:25: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'S Function(S)'.
|
||||
(self::Foo::S*) →* self::Foo::S* f = invalid-expression "pkg/front_end/testcases/extensions/language_issue1182.dart:13:25: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'S Function(S)'.
|
||||
S Function(S) f = x.test;
|
||||
^" in self::Test|get#test<core::num*>(x) as{TypeError} Never;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ library;
|
|||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/extensions/language_issue1182.dart:11:25: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'S Function(S)'.
|
||||
// pkg/front_end/testcases/extensions/language_issue1182.dart:13:25: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'S Function(S)'.
|
||||
// S Function(S) f = x.test;
|
||||
// ^
|
||||
//
|
||||
|
@ -14,7 +14,7 @@ class Foo<S extends core::num*> extends core::Object {
|
|||
: super core::Object::•()
|
||||
;
|
||||
method test1(covariant-by-class self::Foo::S* x) → void {
|
||||
(self::Foo::S*) →* self::Foo::S* f = invalid-expression "pkg/front_end/testcases/extensions/language_issue1182.dart:11:25: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'S Function(S)'.
|
||||
(self::Foo::S*) →* self::Foo::S* f = invalid-expression "pkg/front_end/testcases/extensions/language_issue1182.dart:13:25: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'S Function(S)'.
|
||||
S Function(S) f = x.test;
|
||||
^" in self::Test|get#test<core::num*>(x) as{TypeError} Never;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue