From c4a817cf8e88d6d89d37fd6a4ab3d09e6e0461f7 Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Mon, 3 Nov 2025 14:50:40 +0200 Subject: [PATCH 1/3] #3330. Add tests for static extensions syntax --- .../Static-extensions/syntax_A01_t01.dart | 44 ++++++++++++++++ .../Static-extensions/syntax_A01_t02.dart | 51 +++++++++++++++++++ .../Static-extensions/syntax_A02_t01.dart | 43 ++++++++++++++++ .../Static-extensions/syntax_A02_t02.dart | 43 ++++++++++++++++ .../Static-extensions/syntax_A02_t03.dart | 37 ++++++++++++++ .../Static-extensions/syntax_A02_t04.dart | 49 ++++++++++++++++++ .../Static-extensions/syntax_A02_t05.dart | 33 ++++++++++++ 7 files changed, 300 insertions(+) create mode 100644 LanguageFeatures/Static-extensions/syntax_A01_t01.dart create mode 100644 LanguageFeatures/Static-extensions/syntax_A01_t02.dart create mode 100644 LanguageFeatures/Static-extensions/syntax_A02_t01.dart create mode 100644 LanguageFeatures/Static-extensions/syntax_A02_t02.dart create mode 100644 LanguageFeatures/Static-extensions/syntax_A02_t03.dart create mode 100644 LanguageFeatures/Static-extensions/syntax_A02_t04.dart create mode 100644 LanguageFeatures/Static-extensions/syntax_A02_t05.dart diff --git a/LanguageFeatures/Static-extensions/syntax_A01_t01.dart b/LanguageFeatures/Static-extensions/syntax_A01_t01.dart new file mode 100644 index 0000000000..c4973eb619 --- /dev/null +++ b/LanguageFeatures/Static-extensions/syntax_A01_t01.dart @@ -0,0 +1,44 @@ +// Copyright (c) 2025, 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. + +/// @assertion It is no longer an error to declare a factory constructor, +/// redirecting or not, or a redirecting generative constructor in an extension +/// declaration that has an on-declaration (defined later in this section), and +/// both kinds can be constant or not. +/// +/// @description Checks that that it is a compile-time error to declare a +/// factory constructor in an extension declaration that has no on-declaration. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +class C {} + +class D extends C {} + +extension type ET(int v) {} + +extension Ext1 { + factory C.foo() => D(); +//^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + + factory C.bar() = C.new; +//^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +extension Ext2 { + factory ET.foo(int v) = ET.new; +//^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + print(C); + print(ET); +} diff --git a/LanguageFeatures/Static-extensions/syntax_A01_t02.dart b/LanguageFeatures/Static-extensions/syntax_A01_t02.dart new file mode 100644 index 0000000000..1872d2cf58 --- /dev/null +++ b/LanguageFeatures/Static-extensions/syntax_A01_t02.dart @@ -0,0 +1,51 @@ +// Copyright (c) 2025, 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. + +/// @assertion It is no longer an error to declare a factory constructor, +/// redirecting or not, or a redirecting generative constructor in an extension +/// declaration that has an on-declaration (defined later in this section), and +/// both kinds can be constant or not. +/// +/// @description Checks that that it is a compile-time error to declare a +/// redirecting generative constructor in an extension declaration that has no +/// on-declaration. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +class C {} + +extension type ET(int v) {} + +enum E { + e0; + const E(); +} + +extension Ext1 { + C.foo() : this(); +//^ +// [analyzer] unspecified +// [cfe] unspecified +} + +extension Ext2 { + ET.foo(int v) : this(); +//^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +extension Ext3 { + const E.foo() : this(); +//^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + print(C); + print(ET); + print(E); +} diff --git a/LanguageFeatures/Static-extensions/syntax_A02_t01.dart b/LanguageFeatures/Static-extensions/syntax_A02_t01.dart new file mode 100644 index 0000000000..fcc927af2f --- /dev/null +++ b/LanguageFeatures/Static-extensions/syntax_A02_t01.dart @@ -0,0 +1,43 @@ +// Copyright (c) 2025, 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. + +/// @assertion It is no longer an error to declare a factory constructor, +/// redirecting or not, or a redirecting generative constructor in an extension +/// declaration that has an on-declaration (defined later in this section), and +/// both kinds can be constant or not. +/// +/// @description Checks that that it is not an error to declare a factory +/// constructor in an extension declaration that has an on-declaration. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +import '../../Utils/expect.dart'; + +class C { + int v; + C(this.v); +} + +class D extends C { + D(super.v); +} + +extension type ET(int v) {} + +extension ExtC on C { + factory C.foo() => D(0); + + factory C.bar(int v) = C.new; +} + +extension ExtET on ET { + factory ET.baz(int v) = ET.new; +} + +main() { + Expect.equals(0, C.foo().v); + Expect.equals(1, C.bar(1).v); + Expect.equals(2, ET.baz(2).v); +} diff --git a/LanguageFeatures/Static-extensions/syntax_A02_t02.dart b/LanguageFeatures/Static-extensions/syntax_A02_t02.dart new file mode 100644 index 0000000000..4e8a506de0 --- /dev/null +++ b/LanguageFeatures/Static-extensions/syntax_A02_t02.dart @@ -0,0 +1,43 @@ +// Copyright (c) 2025, 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. + +/// @assertion It is no longer an error to declare a factory constructor, +/// redirecting or not, or a redirecting generative constructor in an extension +/// declaration that has an on-declaration (defined later in this section), and +/// both kinds can be constant or not. +/// +/// @description Checks that that it is not an error to declare a constant +/// factory constructor in an extension declaration that has an on-declaration. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +import '../../Utils/expect.dart'; + +class C { + final int v; + const C(this.v); +} + +class D extends C { + const D(super.v); +} + +extension type const ET(int v) {} + +extension ExtC on C { + const factory C.foo() => const D(0); + + const factory C.bar(int v) = C.new; +} + +extension ExtET on ET { + const factory ET.baz(int v) = ET.new; +} + +main() { + Expect.equals(0, const C.foo().v); + Expect.equals(1, const C.bar(1).v); + Expect.equals(2, const ET.baz(2).v); +} diff --git a/LanguageFeatures/Static-extensions/syntax_A02_t03.dart b/LanguageFeatures/Static-extensions/syntax_A02_t03.dart new file mode 100644 index 0000000000..45ad5d882a --- /dev/null +++ b/LanguageFeatures/Static-extensions/syntax_A02_t03.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2025, 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. + +/// @assertion It is no longer an error to declare a factory constructor, +/// redirecting or not, or a redirecting generative constructor in an extension +/// declaration that has an on-declaration (defined later in this section), and +/// both kinds can be constant or not. +/// +/// @description Checks that that it is not an error to declare a redirecting +/// generative constructor in an extension declaration that has an +/// on-declaration. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +import '../../Utils/expect.dart'; + +class C { + int v; + C(this.v); +} + +extension type ET(int v) {} + +extension ExtC on C { + C.foo() : this(0); +} + +extension ExtET on ET { + ET.bar() : this(1); +} + +main() { + Expect.equals(0, C.foo().v); + Expect.equals(1, ET.bar().v); +} diff --git a/LanguageFeatures/Static-extensions/syntax_A02_t04.dart b/LanguageFeatures/Static-extensions/syntax_A02_t04.dart new file mode 100644 index 0000000000..5bf2cbcb67 --- /dev/null +++ b/LanguageFeatures/Static-extensions/syntax_A02_t04.dart @@ -0,0 +1,49 @@ +// Copyright (c) 2025, 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. + +/// @assertion It is no longer an error to declare a factory constructor, +/// redirecting or not, or a redirecting generative constructor in an extension +/// declaration that has an on-declaration (defined later in this section), and +/// both kinds can be constant or not. +/// +/// @description Checks that that it is not an error to declare a constant +/// redirecting generative constructor in an extension declaration that has an +/// on-declaration. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +import '../../Utils/expect.dart'; + +class C { + final int v; + const C(this.v); +} + +extension type const ET(int v) {} + +enum E { + e0(0), e1.baz(); + + final int v; + const E(this.v); +} + +extension ExtC on C { + const C.foo() : this(0); +} + +extension ExtET on ET { + const ET.bar() : this(1); +} + +extension ExtE on E { + const E.baz() : this(2); +} + +main() { + Expect.equals(0, C.foo().v); + Expect.equals(1, ET.bar().v); + Expect.equals(2, E.e1.v); +} diff --git a/LanguageFeatures/Static-extensions/syntax_A02_t05.dart b/LanguageFeatures/Static-extensions/syntax_A02_t05.dart new file mode 100644 index 0000000000..7ea3f77dbb --- /dev/null +++ b/LanguageFeatures/Static-extensions/syntax_A02_t05.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2025, 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. + +/// @assertion It is no longer an error to declare a factory constructor, +/// redirecting or not, or a redirecting generative constructor in an extension +/// declaration that has an on-declaration (defined later in this section), and +/// both kinds can be constant or not. +/// +/// @description Checks that that it is not a compile-time error to declare a +/// non-constant constant redirecting generative constructor in an extension +/// declaration on an enum. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +enum E { + e0(0); + + final int v; + const E(this.v); +} + +extension ExtE on E { + E.baz() : this(1); +//^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + print(E); +} From e55d825b9432cdbc850480b261ef0d85bd0d16bb Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Mon, 3 Nov 2025 15:52:37 +0200 Subject: [PATCH 2/3] Fix "on-declaration" tests --- .../Static-extensions/syntax_A01_t01.dart | 23 ++++-------- .../Static-extensions/syntax_A01_t02.dart | 36 ++++++------------ .../Static-extensions/syntax_A01_t03.dart | 37 +++++++++++++++++++ .../Static-extensions/syntax_A01_t04.dart | 29 +++++++++++++++ .../Static-extensions/syntax_A01_t05.dart | 32 ++++++++++++++++ 5 files changed, 117 insertions(+), 40 deletions(-) create mode 100644 LanguageFeatures/Static-extensions/syntax_A01_t03.dart create mode 100644 LanguageFeatures/Static-extensions/syntax_A01_t04.dart create mode 100644 LanguageFeatures/Static-extensions/syntax_A01_t05.dart diff --git a/LanguageFeatures/Static-extensions/syntax_A01_t01.dart b/LanguageFeatures/Static-extensions/syntax_A01_t01.dart index c4973eb619..ff2137f4f2 100644 --- a/LanguageFeatures/Static-extensions/syntax_A01_t01.dart +++ b/LanguageFeatures/Static-extensions/syntax_A01_t01.dart @@ -6,33 +6,27 @@ /// redirecting or not, or a redirecting generative constructor in an extension /// declaration that has an on-declaration (defined later in this section), and /// both kinds can be constant or not. +/// ... +/// For the purpose of identifying the on-declaration of a given extension, the +/// types `void`, `dynamic`, and `Never` are not considered to be classes, and +/// neither are record types or function types. /// /// @description Checks that that it is a compile-time error to declare a /// factory constructor in an extension declaration that has no on-declaration. +/// Test extension on type `void`. /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=static-extensions class C {} -class D extends C {} - -extension type ET(int v) {} - -extension Ext1 { - factory C.foo() => D(); +extension Ext on void { + factory void.foo() => 42; //^^^^^^^ // [analyzer] unspecified // [cfe] unspecified - factory C.bar() = C.new; -//^^^^^^^ -// [analyzer] unspecified -// [cfe] unspecified -} - -extension Ext2 { - factory ET.foo(int v) = ET.new; + factory void.bar() = C.new; //^^^^^^^ // [analyzer] unspecified // [cfe] unspecified @@ -40,5 +34,4 @@ extension Ext2 { main() { print(C); - print(ET); } diff --git a/LanguageFeatures/Static-extensions/syntax_A01_t02.dart b/LanguageFeatures/Static-extensions/syntax_A01_t02.dart index 1872d2cf58..7666b5c19c 100644 --- a/LanguageFeatures/Static-extensions/syntax_A01_t02.dart +++ b/LanguageFeatures/Static-extensions/syntax_A01_t02.dart @@ -6,46 +6,32 @@ /// redirecting or not, or a redirecting generative constructor in an extension /// declaration that has an on-declaration (defined later in this section), and /// both kinds can be constant or not. +/// ... +/// For the purpose of identifying the on-declaration of a given extension, the +/// types `void`, `dynamic`, and `Never` are not considered to be classes, and +/// neither are record types or function types. /// /// @description Checks that that it is a compile-time error to declare a -/// redirecting generative constructor in an extension declaration that has no -/// on-declaration. +/// factory constructor in an extension declaration that has no on-declaration. +/// Test extension on type `dynamic`. /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=static-extensions class C {} -extension type ET(int v) {} - -enum E { - e0; - const E(); -} - -extension Ext1 { - C.foo() : this(); -//^ -// [analyzer] unspecified -// [cfe] unspecified -} - -extension Ext2 { - ET.foo(int v) : this(); -//^^ +extension Ext on dynamic { + factory dynamic.foo() => C(); +//^^^^^^^ // [analyzer] unspecified // [cfe] unspecified -} -extension Ext3 { - const E.foo() : this(); -//^^ + factory dynamic.bar() = C.new; +//^^^^^^^ // [analyzer] unspecified // [cfe] unspecified } main() { print(C); - print(ET); - print(E); } diff --git a/LanguageFeatures/Static-extensions/syntax_A01_t03.dart b/LanguageFeatures/Static-extensions/syntax_A01_t03.dart new file mode 100644 index 0000000000..1b54acd7f0 --- /dev/null +++ b/LanguageFeatures/Static-extensions/syntax_A01_t03.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2025, 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. + +/// @assertion It is no longer an error to declare a factory constructor, +/// redirecting or not, or a redirecting generative constructor in an extension +/// declaration that has an on-declaration (defined later in this section), and +/// both kinds can be constant or not. +/// ... +/// For the purpose of identifying the on-declaration of a given extension, the +/// types `void`, `dynamic`, and `Never` are not considered to be classes, and +/// neither are record types or function types. +/// +/// @description Checks that that it is a compile-time error to declare a +/// factory constructor in an extension declaration that has no on-declaration. +/// Test extension on type `Never`. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +class C {} + +extension Ext on Never { + factory Never.foo() => C(); +//^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + + factory Never.bar() = C.new; +//^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + print(C); +} diff --git a/LanguageFeatures/Static-extensions/syntax_A01_t04.dart b/LanguageFeatures/Static-extensions/syntax_A01_t04.dart new file mode 100644 index 0000000000..969b1fd439 --- /dev/null +++ b/LanguageFeatures/Static-extensions/syntax_A01_t04.dart @@ -0,0 +1,29 @@ +// Copyright (c) 2025, 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. + +/// @assertion It is no longer an error to declare a factory constructor, +/// redirecting or not, or a redirecting generative constructor in an extension +/// declaration that has an on-declaration (defined later in this section), and +/// both kinds can be constant or not. +/// ... +/// For the purpose of identifying the on-declaration of a given extension, the +/// types `void`, `dynamic`, and `Never` are not considered to be classes, and +/// neither are record types or function types. +/// +/// @description Checks that that it is a compile-time error to declare a +/// factory constructor in an extension declaration that has no on-declaration. +/// Test extension on type `Record`. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +extension Ext on Record { + factory Record.foo() => (); +//^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { +} diff --git a/LanguageFeatures/Static-extensions/syntax_A01_t05.dart b/LanguageFeatures/Static-extensions/syntax_A01_t05.dart new file mode 100644 index 0000000000..732cc4dd4b --- /dev/null +++ b/LanguageFeatures/Static-extensions/syntax_A01_t05.dart @@ -0,0 +1,32 @@ +// Copyright (c) 2025, 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. + +/// @assertion It is no longer an error to declare a factory constructor, +/// redirecting or not, or a redirecting generative constructor in an extension +/// declaration that has an on-declaration (defined later in this section), and +/// both kinds can be constant or not. +/// ... +/// For the purpose of identifying the on-declaration of a given extension, the +/// types `void`, `dynamic`, and `Never` are not considered to be classes, and +/// neither are record types or function types. +/// +/// @description Checks that that it is a compile-time error to declare a +/// factory constructor in an extension declaration that has no on-declaration. +/// Test extension on a function type. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +typedef F = void Function(); + +extension Ext on F { + factory F.foo() => () {}; +//^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + print(F); +} From 6120737bfbff01561c6a659d5244316d0a2a5ee6 Mon Sep 17 00:00:00 2001 From: "Sergey G. Grekhov" Date: Mon, 3 Nov 2025 15:59:09 +0200 Subject: [PATCH 3/3] Fix spec parser failure --- LanguageFeatures/Static-extensions/syntax_A01_t01.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/LanguageFeatures/Static-extensions/syntax_A01_t01.dart b/LanguageFeatures/Static-extensions/syntax_A01_t01.dart index ff2137f4f2..36f5743f9f 100644 --- a/LanguageFeatures/Static-extensions/syntax_A01_t01.dart +++ b/LanguageFeatures/Static-extensions/syntax_A01_t01.dart @@ -20,13 +20,15 @@ class C {} +typedef Void = void; + extension Ext on void { - factory void.foo() => 42; + factory Void.foo() => 42; //^^^^^^^ // [analyzer] unspecified // [cfe] unspecified - factory void.bar() = C.new; + factory Void.bar() = C.new; //^^^^^^^ // [analyzer] unspecified // [cfe] unspecified