From ef6d68c040a728200d31f41d1864d69e53863cfc Mon Sep 17 00:00:00 2001 From: Chloe Stefantsova Date: Wed, 13 Mar 2024 09:43:57 +0000 Subject: [PATCH] [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 Commit-Queue: Chloe Stefantsova --- .../lib/src/fasta/kernel/internal_ast.dart | 10 ++-- .../testcases/dart2js/issue55135.dart | 26 ++++++++++ .../dart2js/issue55135.dart.strong.expect | 47 +++++++++++++++++++ .../issue55135.dart.strong.transformed.expect | 47 +++++++++++++++++++ .../issue55135.dart.textual_outline.expect | 16 +++++++ ...55135.dart.textual_outline_modelled.expect | 16 +++++++ .../dart2js/issue55135.dart.weak.expect | 47 +++++++++++++++++++ .../issue55135.dart.weak.modular.expect | 47 +++++++++++++++++++ .../issue55135.dart.weak.outline.expect | 37 +++++++++++++++ .../issue55135.dart.weak.transformed.expect | 47 +++++++++++++++++++ .../testcases/extension_types/issue55135.dart | 26 ++++++++++ .../issue55135.dart.strong.expect | 43 +++++++++++++++++ .../issue55135.dart.strong.transformed.expect | 43 +++++++++++++++++ .../issue55135.dart.textual_outline.expect | 16 +++++++ ...55135.dart.textual_outline_modelled.expect | 16 +++++++ .../issue55135.dart.weak.expect | 43 +++++++++++++++++ .../issue55135.dart.weak.modular.expect | 43 +++++++++++++++++ .../issue55135.dart.weak.outline.expect | 33 +++++++++++++ .../issue55135.dart.weak.transformed.expect | 43 +++++++++++++++++ 19 files changed, 641 insertions(+), 5 deletions(-) create mode 100644 pkg/front_end/testcases/dart2js/issue55135.dart create mode 100644 pkg/front_end/testcases/dart2js/issue55135.dart.strong.expect create mode 100644 pkg/front_end/testcases/dart2js/issue55135.dart.strong.transformed.expect create mode 100644 pkg/front_end/testcases/dart2js/issue55135.dart.textual_outline.expect create mode 100644 pkg/front_end/testcases/dart2js/issue55135.dart.textual_outline_modelled.expect create mode 100644 pkg/front_end/testcases/dart2js/issue55135.dart.weak.expect create mode 100644 pkg/front_end/testcases/dart2js/issue55135.dart.weak.modular.expect create mode 100644 pkg/front_end/testcases/dart2js/issue55135.dart.weak.outline.expect create mode 100644 pkg/front_end/testcases/dart2js/issue55135.dart.weak.transformed.expect create mode 100644 pkg/front_end/testcases/extension_types/issue55135.dart create mode 100644 pkg/front_end/testcases/extension_types/issue55135.dart.strong.expect create mode 100644 pkg/front_end/testcases/extension_types/issue55135.dart.strong.transformed.expect create mode 100644 pkg/front_end/testcases/extension_types/issue55135.dart.textual_outline.expect create mode 100644 pkg/front_end/testcases/extension_types/issue55135.dart.textual_outline_modelled.expect create mode 100644 pkg/front_end/testcases/extension_types/issue55135.dart.weak.expect create mode 100644 pkg/front_end/testcases/extension_types/issue55135.dart.weak.modular.expect create mode 100644 pkg/front_end/testcases/extension_types/issue55135.dart.weak.outline.expect create mode 100644 pkg/front_end/testcases/extension_types/issue55135.dart.weak.transformed.expect diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart index 0d945ade712..25ccf51baca 100644 --- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart +++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart @@ -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 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; diff --git a/pkg/front_end/testcases/dart2js/issue55135.dart b/pkg/front_end/testcases/dart2js/issue55135.dart new file mode 100644 index 00000000000..3028be17de1 --- /dev/null +++ b/pkg/front_end/testcases/dart2js/issue55135.dart @@ -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}'."; + } +} diff --git a/pkg/front_end/testcases/dart2js/issue55135.dart.strong.expect b/pkg/front_end/testcases/dart2js/issue55135.dart.strong.expect new file mode 100644 index 00000000000..bf9f2bf77dd --- /dev/null +++ b/pkg/front_end/testcases/dart2js/issue55135.dart.strong.expect @@ -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}'."; + } +} diff --git a/pkg/front_end/testcases/dart2js/issue55135.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/issue55135.dart.strong.transformed.expect new file mode 100644 index 00000000000..bf9f2bf77dd --- /dev/null +++ b/pkg/front_end/testcases/dart2js/issue55135.dart.strong.transformed.expect @@ -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}'."; + } +} diff --git a/pkg/front_end/testcases/dart2js/issue55135.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/issue55135.dart.textual_outline.expect new file mode 100644 index 00000000000..7cff9fce38d --- /dev/null +++ b/pkg/front_end/testcases/dart2js/issue55135.dart.textual_outline.expect @@ -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) {} diff --git a/pkg/front_end/testcases/dart2js/issue55135.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/issue55135.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..86ce38fd3fc --- /dev/null +++ b/pkg/front_end/testcases/dart2js/issue55135.dart.textual_outline_modelled.expect @@ -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() {} diff --git a/pkg/front_end/testcases/dart2js/issue55135.dart.weak.expect b/pkg/front_end/testcases/dart2js/issue55135.dart.weak.expect new file mode 100644 index 00000000000..bf9f2bf77dd --- /dev/null +++ b/pkg/front_end/testcases/dart2js/issue55135.dart.weak.expect @@ -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}'."; + } +} diff --git a/pkg/front_end/testcases/dart2js/issue55135.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/issue55135.dart.weak.modular.expect new file mode 100644 index 00000000000..bf9f2bf77dd --- /dev/null +++ b/pkg/front_end/testcases/dart2js/issue55135.dart.weak.modular.expect @@ -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}'."; + } +} diff --git a/pkg/front_end/testcases/dart2js/issue55135.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/issue55135.dart.weak.outline.expect new file mode 100644 index 00000000000..1b030722075 --- /dev/null +++ b/pkg/front_end/testcases/dart2js/issue55135.dart.weak.outline.expect @@ -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 + ; diff --git a/pkg/front_end/testcases/dart2js/issue55135.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/issue55135.dart.weak.transformed.expect new file mode 100644 index 00000000000..bf9f2bf77dd --- /dev/null +++ b/pkg/front_end/testcases/dart2js/issue55135.dart.weak.transformed.expect @@ -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}'."; + } +} diff --git a/pkg/front_end/testcases/extension_types/issue55135.dart b/pkg/front_end/testcases/extension_types/issue55135.dart new file mode 100644 index 00000000000..3028be17de1 --- /dev/null +++ b/pkg/front_end/testcases/extension_types/issue55135.dart @@ -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}'."; + } +} diff --git a/pkg/front_end/testcases/extension_types/issue55135.dart.strong.expect b/pkg/front_end/testcases/extension_types/issue55135.dart.strong.expect new file mode 100644 index 00000000000..06fe05dd71b --- /dev/null +++ b/pkg/front_end/testcases/extension_types/issue55135.dart.strong.expect @@ -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}'."; + } +} diff --git a/pkg/front_end/testcases/extension_types/issue55135.dart.strong.transformed.expect b/pkg/front_end/testcases/extension_types/issue55135.dart.strong.transformed.expect new file mode 100644 index 00000000000..06fe05dd71b --- /dev/null +++ b/pkg/front_end/testcases/extension_types/issue55135.dart.strong.transformed.expect @@ -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}'."; + } +} diff --git a/pkg/front_end/testcases/extension_types/issue55135.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/issue55135.dart.textual_outline.expect new file mode 100644 index 00000000000..7cff9fce38d --- /dev/null +++ b/pkg/front_end/testcases/extension_types/issue55135.dart.textual_outline.expect @@ -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) {} diff --git a/pkg/front_end/testcases/extension_types/issue55135.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extension_types/issue55135.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..86ce38fd3fc --- /dev/null +++ b/pkg/front_end/testcases/extension_types/issue55135.dart.textual_outline_modelled.expect @@ -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() {} diff --git a/pkg/front_end/testcases/extension_types/issue55135.dart.weak.expect b/pkg/front_end/testcases/extension_types/issue55135.dart.weak.expect new file mode 100644 index 00000000000..06fe05dd71b --- /dev/null +++ b/pkg/front_end/testcases/extension_types/issue55135.dart.weak.expect @@ -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}'."; + } +} diff --git a/pkg/front_end/testcases/extension_types/issue55135.dart.weak.modular.expect b/pkg/front_end/testcases/extension_types/issue55135.dart.weak.modular.expect new file mode 100644 index 00000000000..06fe05dd71b --- /dev/null +++ b/pkg/front_end/testcases/extension_types/issue55135.dart.weak.modular.expect @@ -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}'."; + } +} diff --git a/pkg/front_end/testcases/extension_types/issue55135.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/issue55135.dart.weak.outline.expect new file mode 100644 index 00000000000..9ba1fd93e1f --- /dev/null +++ b/pkg/front_end/testcases/extension_types/issue55135.dart.weak.outline.expect @@ -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 + ; diff --git a/pkg/front_end/testcases/extension_types/issue55135.dart.weak.transformed.expect b/pkg/front_end/testcases/extension_types/issue55135.dart.weak.transformed.expect new file mode 100644 index 00000000000..06fe05dd71b --- /dev/null +++ b/pkg/front_end/testcases/extension_types/issue55135.dart.weak.transformed.expect @@ -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}'."; + } +}