[cfe] Add ExtensionTypeRepresentationFieldInitializer.replaceChild

The added method is required for the resolution of redirection targets
to work: it replaces the immediate target invocation node with the
final target invocation node.

Closes https://github.com/dart-lang/sdk/issues/55135

Change-Id: I421f182192aae17f4bd3dcfe6d8216befde0e93e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/357161
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
Chloe Stefantsova
2024-03-13 09:43:57 +00:00
committed by Commit Queue
parent c506bb80ba
commit ef6d68c040
19 changed files with 641 additions and 5 deletions
@@ -350,11 +350,6 @@ abstract class InternalExpression extends AuxiliaryExpression {
/// Common base class for internal initializers.
abstract class InternalInitializer extends AuxiliaryInitializer {
@override
void replaceChild(TreeNode child, TreeNode replacement) {
// Do nothing. The node should not be part of the resulting AST, anyway.
}
@override
void visitChildren(Visitor<dynamic> v) =>
unsupported("${runtimeType}.visitChildren", -1, null);
@@ -3374,6 +3369,11 @@ class ExtensionTypeRepresentationFieldInitializer extends InternalInitializer {
value.parent = this;
}
@override
void transformChildren(Transformer v) {
value = v.transform(value)..parent = this;
}
/// [Procedure] that represents the representation field.
Procedure get field => fieldReference.asProcedure;
@@ -0,0 +1,26 @@
// Copyright (c) 2024, 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.
class B implements A {
final int x = 1;
}
abstract class A {
int get x;
factory A() = B;
}
extension type C._(A point) implements A {
C() : point = A(); // << initializer is redirecting factory
}
void main() {
expectEquals(A().x, 1);
expectEquals(C().x, 1);
}
expectEquals(x, y) {
if (x != y) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}
@@ -0,0 +1,47 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x = 1;
synthetic constructor •() → self::B
: super core::Object::•()
;
static method _#new#tearOff() → self::B
return new self::B::•();
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
static method _#new#tearOff() → self::A
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = point;
return #this;
}
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = new self::B::•();
return #this;
}
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void {
self::expectEquals(new self::B::•().{self::A::x}{core::int}, 1);
self::expectEquals(self::C|constructor#().{self::A::x}{core::int}, 1);
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}
@@ -0,0 +1,47 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x = 1;
synthetic constructor •() → self::B
: super core::Object::•()
;
static method _#new#tearOff() → self::B
return new self::B::•();
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
static method _#new#tearOff() → self::A
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = point;
return #this;
}
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = new self::B::•();
return #this;
}
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void {
self::expectEquals(new self::B::•().{self::A::x}{core::int}, 1);
self::expectEquals(self::C|constructor#().{self::A::x}{core::int}, 1);
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}
@@ -0,0 +1,16 @@
class B implements A {
final int x = 1;
}
abstract class A {
int get x;
factory A() = B;
}
extension type C._(A point) implements A {
C() : point = A();
}
void main() {}
expectEquals(x, y) {}
@@ -0,0 +1,16 @@
abstract class A {
factory A() = B;
int get x;
}
class B implements A {
final int x = 1;
}
expectEquals(x, y) {}
extension type C._(A point) implements A {
C() : point = A();
}
void main() {}
@@ -0,0 +1,47 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x = 1;
synthetic constructor •() → self::B
: super core::Object::•()
;
static method _#new#tearOff() → self::B
return new self::B::•();
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
static method _#new#tearOff() → self::A
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = point;
return #this;
}
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = new self::B::•();
return #this;
}
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void {
self::expectEquals(new self::B::•().{self::A::x}{core::int}, 1);
self::expectEquals(self::C|constructor#().{self::A::x}{core::int}, 1);
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}
@@ -0,0 +1,47 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x = 1;
synthetic constructor •() → self::B
: super core::Object::•()
;
static method _#new#tearOff() → self::B
return new self::B::•();
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
static method _#new#tearOff() → self::A
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = point;
return #this;
}
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = new self::B::•();
return #this;
}
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void {
self::expectEquals(new self::B::•().{self::A::x}{core::int}, 1);
self::expectEquals(self::C|constructor#().{self::A::x}{core::int}, 1);
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}
@@ -0,0 +1,37 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x;
synthetic constructor •() → self::B
;
static method _#new#tearOff() → self::B
return new self::B::•();
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
static method _#new#tearOff() → self::A
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */
;
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */
;
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void
;
static method expectEquals(dynamic x, dynamic y) → dynamic
;
@@ -0,0 +1,47 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x = 1;
synthetic constructor •() → self::B
: super core::Object::•()
;
static method _#new#tearOff() → self::B
return new self::B::•();
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
static method _#new#tearOff() → self::A
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = point;
return #this;
}
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = new self::B::•();
return #this;
}
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void {
self::expectEquals(new self::B::•().{self::A::x}{core::int}, 1);
self::expectEquals(self::C|constructor#().{self::A::x}{core::int}, 1);
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}
@@ -0,0 +1,26 @@
// Copyright (c) 2024, 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.
class B implements A {
final int x = 1;
}
abstract class A {
int get x;
factory A() = B;
}
extension type C._(A point) implements A {
C() : point = A(); // << initializer is redirecting factory
}
void main() {
expectEquals(A().x, 1);
expectEquals(C().x, 1);
}
expectEquals(x, y) {
if (x != y) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}
@@ -0,0 +1,43 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x = 1;
synthetic constructor •() → self::B
: super core::Object::•()
;
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = point;
return #this;
}
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = new self::B::•();
return #this;
}
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void {
self::expectEquals(new self::B::•().{self::A::x}{core::int}, 1);
self::expectEquals(self::C|constructor#().{self::A::x}{core::int}, 1);
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}
@@ -0,0 +1,43 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x = 1;
synthetic constructor •() → self::B
: super core::Object::•()
;
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = point;
return #this;
}
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = new self::B::•();
return #this;
}
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void {
self::expectEquals(new self::B::•().{self::A::x}{core::int}, 1);
self::expectEquals(self::C|constructor#().{self::A::x}{core::int}, 1);
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}
@@ -0,0 +1,16 @@
class B implements A {
final int x = 1;
}
abstract class A {
int get x;
factory A() = B;
}
extension type C._(A point) implements A {
C() : point = A();
}
void main() {}
expectEquals(x, y) {}
@@ -0,0 +1,16 @@
abstract class A {
factory A() = B;
int get x;
}
class B implements A {
final int x = 1;
}
expectEquals(x, y) {}
extension type C._(A point) implements A {
C() : point = A();
}
void main() {}
@@ -0,0 +1,43 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x = 1;
synthetic constructor •() → self::B
: super core::Object::•()
;
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = point;
return #this;
}
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = new self::B::•();
return #this;
}
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void {
self::expectEquals(new self::B::•().{self::A::x}{core::int}, 1);
self::expectEquals(self::C|constructor#().{self::A::x}{core::int}, 1);
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}
@@ -0,0 +1,43 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x = 1;
synthetic constructor •() → self::B
: super core::Object::•()
;
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = point;
return #this;
}
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = new self::B::•();
return #this;
}
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void {
self::expectEquals(new self::B::•().{self::A::x}{core::int}, 1);
self::expectEquals(self::C|constructor#().{self::A::x}{core::int}, 1);
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}
@@ -0,0 +1,33 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x;
synthetic constructor •() → self::B
;
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */
;
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */
;
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void
;
static method expectEquals(dynamic x, dynamic y) → dynamic
;
@@ -0,0 +1,43 @@
library;
import self as self;
import "dart:core" as core;
class B extends core::Object implements self::A {
final field core::int x = 1;
synthetic constructor •() → self::B
: super core::Object::•()
;
}
abstract class A extends core::Object {
abstract get x() → core::int;
static factory •() → self::A /* redirection-target: self::B::• */
return new self::B::•();
}
extension type C(self::A point) implements self::A {
abstract extension-type-member representation-field get point() → self::A;
constructor _ = self::C|constructor#_;
constructor tearoff _ = self::C|constructor#_#_#tearOff;
constructor • = self::C|constructor#;
constructor tearoff • = self::C|constructor#_#new#tearOff;
}
static extension-type-member method C|constructor#_(self::A point) → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = point;
return #this;
}
static extension-type-member method C|constructor#_#_#tearOff(self::A point) → self::C /* erasure=self::A */
return self::C|constructor#_(point);
static extension-type-member method C|constructor#() → self::C /* erasure=self::A */ {
lowered final self::C /* erasure=self::A */ #this = new self::B::•();
return #this;
}
static extension-type-member method C|constructor#_#new#tearOff() → self::C /* erasure=self::A */
return self::C|constructor#();
static method main() → void {
self::expectEquals(new self::B::•().{self::A::x}{core::int}, 1);
self::expectEquals(self::C|constructor#().{self::A::x}{core::int}, 1);
}
static method expectEquals(dynamic x, dynamic y) → dynamic {
if(!(x =={core::Object::==}{(core::Object) → core::bool} y)) {
throw "Expected equal values, got '${x}' and '${y}'.";
}
}