From f4616542ee7580642ce05f228e1ab9c05bd91f62 Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Wed, 5 Nov 2025 11:58:09 +0200 Subject: [PATCH 1/3] #3330. Add static extensions tests. Part 2. --- .../static_member_A03_t01.dart | 68 +++++++++++++++++ .../static_member_A03_t02.dart | 71 +++++++++++++++++ .../static_member_A04_t01.dart | 72 ++++++++++++++++++ .../static_member_A05_t01.dart | 58 ++++++++++++++ .../static_member_A05_t02.dart | 58 ++++++++++++++ .../static_member_A05_t03.dart | 58 ++++++++++++++ .../static_member_A05_t04.dart | 76 +++++++++++++++++++ 7 files changed, 461 insertions(+) create mode 100644 LanguageFeatures/Static-extensions/static_member_A03_t01.dart create mode 100644 LanguageFeatures/Static-extensions/static_member_A03_t02.dart create mode 100644 LanguageFeatures/Static-extensions/static_member_A04_t01.dart create mode 100644 LanguageFeatures/Static-extensions/static_member_A05_t01.dart create mode 100644 LanguageFeatures/Static-extensions/static_member_A05_t02.dart create mode 100644 LanguageFeatures/Static-extensions/static_member_A05_t03.dart create mode 100644 LanguageFeatures/Static-extensions/static_member_A05_t04.dart diff --git a/LanguageFeatures/Static-extensions/static_member_A03_t01.dart b/LanguageFeatures/Static-extensions/static_member_A03_t01.dart new file mode 100644 index 0000000000..f1929a12fa --- /dev/null +++ b/LanguageFeatures/Static-extensions/static_member_A03_t01.dart @@ -0,0 +1,68 @@ +// 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 Consider an expression `e` which is a member invocation with +/// syntactic receiver `C` and an associated member name `m`. Assume that `m` is +/// a static member declared by `D`. The static analysis and dynamic semantics +/// of this expression is the same as in Dart before the introduction of this +/// feature. +/// +/// @description Checks that if `C` contains static member with the basename `m` +/// then it is not an error for extensions to declare a static members with the +/// same basename. Invocation of `m` will invoke the appropriate member. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +import '../../Utils/expect.dart'; + +String log = ""; + +class C { + static int foo = 42; +} + +mixin M { + static int foo() => 42; +} + +extension type ET(int _) { + static int get foo => 42; +} + +enum E { + e0; + static void set foo(int v) { + log = "$v"; + } +} + +extension ExtC on C { + static String foo() => "ExtC"; +} + +extension ExtM on M { + static String foo() => "ExtM"; +} + +extension ExtET on ET { + static String foo() => "ExtET"; +} + +extension ExtE on E { + static String foo() => "ExtE"; +} + +main() { + Expect.equals(42, C.foo); + Expect.equals(42, M.foo()); + Expect.equals(42, ET.foo); + E.foo = 42; + Expect.equals("42", log); + + Expect.equals("ExtC", ExtC.foo()); + Expect.equals("ExtM", ExtM.foo()); + Expect.equals("ExtET", ExtET.foo()); + Expect.equals("ExtE", ExtE.foo()); +} diff --git a/LanguageFeatures/Static-extensions/static_member_A03_t02.dart b/LanguageFeatures/Static-extensions/static_member_A03_t02.dart new file mode 100644 index 0000000000..47634cbbd8 --- /dev/null +++ b/LanguageFeatures/Static-extensions/static_member_A03_t02.dart @@ -0,0 +1,71 @@ +// 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 Consider an expression `e` which is a member invocation with +/// syntactic receiver `C` and an associated member name `m`. Assume that `m` is +/// a static member declared by `D`. The static analysis and dynamic semantics +/// of this expression is the same as in Dart before the introduction of this +/// feature. +/// +/// @description Checks that if `C` contains an instance member with the +/// basename `m` then it is not an error for extensions to declare a static +/// member with the same basename. Invocation of `m` will invoke the appropriate +/// member. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +import '../../Utils/expect.dart'; + +String log = ""; + +class C { + int foo = 42; +} + +mixin M { + int foo() => 42; +} + +class MA = Object with M; + +extension type ET(int _) { + int get foo => 42; +} + +enum E { + e0; + void set foo(int v) { + log = "$v"; + } +} + +extension ExtC on C { + static String foo() => "ExtC"; +} + +extension ExtM on M { + static String foo() => "ExtM"; +} + +extension ExtET on ET { + static String foo() => "ExtET"; +} + +extension ExtE on E { + static String foo() => "ExtE"; +} + +main() { + Expect.equals(42, C().foo); + Expect.equals(42, MA().foo()); + Expect.equals(42, ET(0).foo); + E.e0.foo = 42; + Expect.equals("42", log); + + Expect.equals("ExtC", ExtC.foo()); + Expect.equals("ExtM", ExtM.foo()); + Expect.equals("ExtET", ExtET.foo()); + Expect.equals("ExtE", ExtE.foo()); +} diff --git a/LanguageFeatures/Static-extensions/static_member_A04_t01.dart b/LanguageFeatures/Static-extensions/static_member_A04_t01.dart new file mode 100644 index 0000000000..f203e819ec --- /dev/null +++ b/LanguageFeatures/Static-extensions/static_member_A04_t01.dart @@ -0,0 +1,72 @@ +// 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 Consider an expression `e` which is a member invocation with +/// syntactic receiver `C` and an associated member name `m`. Assume that `m` is +/// a static member declared by `D`. The static analysis and dynamic semantics +/// of this expression is the same as in Dart before the introduction of this +/// feature. +/// ... +/// When `D` declares a static member whose basename is the basename of `m`, but +/// `D` does not declare a static member named `m` or a constructor named `C.m`, +/// a compile-time error occurs. +/// +/// @description Checks that it is a compile-time error if `D` declares a static +/// member whose basename is the basename of `m`, but `D` does not declare a +/// member named `m` +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +class C { + static final int foo = 42; +} + +mixin M { + static int foo() => 42; +} + +extension type ET(int _) { + static int get foo => 42; +} + +enum E { + e0; + static void set foo(int _) {} +} + +extension ExtC on C { + static void set foo(int _) {} +} + +extension ExtM on M { + static void set foo(int _) {} +} + +extension ExtET on ET { + static void set foo(int _) {} +} + +extension ExtE on E { + static int get foo => 42; +} + +main() { + C.foo = 42; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified + M.foo = 42; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified + ET.foo = 42; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified + E.foo; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified +} diff --git a/LanguageFeatures/Static-extensions/static_member_A05_t01.dart b/LanguageFeatures/Static-extensions/static_member_A05_t01.dart new file mode 100644 index 0000000000..b57f75ef07 --- /dev/null +++ b/LanguageFeatures/Static-extensions/static_member_A05_t01.dart @@ -0,0 +1,58 @@ +// 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 Consider an expression `e` which is a member invocation with +/// syntactic receiver `C` and an associated member name `m`. Assume that `m` is +/// a static member declared by `D`. The static analysis and dynamic semantics +/// of this expression is the same as in Dart before the introduction of this +/// feature. +/// ... +/// Assume that it is an extension `E` that declares a static member named `m`. +/// The invocation is then treated as `E.m()`. +/// +/// @description Checks that invocation of `m` is then treated as `E.m()`. Test +/// a static variable as `m`. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +import '../../Utils/expect.dart'; + +class C {} + +mixin M {} + +extension type ET(int _) {} + +enum E { + e0; +} + +extension ExtC on C { + static String foo = "ExtC"; +} + +extension ExtM on M { + static String foo = "ExtM"; +} + +extension ExtET on ET { + static String foo = "ExtET"; +} + +extension ExtE on E { + static String foo = "ExtE"; +} + +main() { + Expect.equals("ExtC", C.foo); + Expect.equals("ExtM", M.foo); + Expect.equals("ExtET", ET.foo); + Expect.equals("ExtE", E.foo); + + Expect.equals("ExtC", ExtC.foo); + Expect.equals("ExtM", ExtM.foo); + Expect.equals("ExtET", ExtET.foo); + Expect.equals("ExtE", ExtE.foo); +} diff --git a/LanguageFeatures/Static-extensions/static_member_A05_t02.dart b/LanguageFeatures/Static-extensions/static_member_A05_t02.dart new file mode 100644 index 0000000000..0fd239781a --- /dev/null +++ b/LanguageFeatures/Static-extensions/static_member_A05_t02.dart @@ -0,0 +1,58 @@ +// 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 Consider an expression `e` which is a member invocation with +/// syntactic receiver `C` and an associated member name `m`. Assume that `m` is +/// a static member declared by `D`. The static analysis and dynamic semantics +/// of this expression is the same as in Dart before the introduction of this +/// feature. +/// ... +/// Assume that it is an extension `E` that declares a static member named `m`. +/// The invocation is then treated as `E.m()`. +/// +/// @description Checks that invocation of `m` is then treated as `E.m()`. Test +/// a static getter as `m`. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +import '../../Utils/expect.dart'; + +class C {} + +mixin M {} + +extension type ET(int _) {} + +enum E { + e0; +} + +extension ExtC on C { + static String get foo => "ExtC"; +} + +extension ExtM on M { + static String get foo => "ExtM"; +} + +extension ExtET on ET { + static String get foo => "ExtET"; +} + +extension ExtE on E { + static String get foo => "ExtE"; +} + +main() { + Expect.equals("ExtC", C.foo); + Expect.equals("ExtM", M.foo); + Expect.equals("ExtET", ET.foo); + Expect.equals("ExtE", E.foo); + + Expect.equals("ExtC", ExtC.foo); + Expect.equals("ExtM", ExtM.foo); + Expect.equals("ExtET", ExtET.foo); + Expect.equals("ExtE", ExtE.foo); +} diff --git a/LanguageFeatures/Static-extensions/static_member_A05_t03.dart b/LanguageFeatures/Static-extensions/static_member_A05_t03.dart new file mode 100644 index 0000000000..f8b4b2aa28 --- /dev/null +++ b/LanguageFeatures/Static-extensions/static_member_A05_t03.dart @@ -0,0 +1,58 @@ +// 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 Consider an expression `e` which is a member invocation with +/// syntactic receiver `C` and an associated member name `m`. Assume that `m` is +/// a static member declared by `D`. The static analysis and dynamic semantics +/// of this expression is the same as in Dart before the introduction of this +/// feature. +/// ... +/// Assume that it is an extension `E` that declares a static member named `m`. +/// The invocation is then treated as `E.m()`. +/// +/// @description Checks that invocation of `m` is then treated as `E.m()`. Test +/// a static getter as `m`. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +import '../../Utils/expect.dart'; + +class C {} + +mixin M {} + +extension type ET(int _) {} + +enum E { + e0; +} + +extension ExtC on C { + static String foo() => "ExtC"; +} + +extension ExtM on M { + static String foo() => "ExtM"; +} + +extension ExtET on ET { + static String foo() => "ExtET"; +} + +extension ExtE on E { + static String foo() => "ExtE"; +} + +main() { + Expect.equals("ExtC", C.foo()); + Expect.equals("ExtM", M.foo()); + Expect.equals("ExtET", ET.foo()); + Expect.equals("ExtE", E.foo()); + + Expect.equals("ExtC", ExtC.foo()); + Expect.equals("ExtM", ExtM.foo()); + Expect.equals("ExtET", ExtET.foo()); + Expect.equals("ExtE", ExtE.foo()); +} diff --git a/LanguageFeatures/Static-extensions/static_member_A05_t04.dart b/LanguageFeatures/Static-extensions/static_member_A05_t04.dart new file mode 100644 index 0000000000..617349bd82 --- /dev/null +++ b/LanguageFeatures/Static-extensions/static_member_A05_t04.dart @@ -0,0 +1,76 @@ +// 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 Consider an expression `e` which is a member invocation with +/// syntactic receiver `C` and an associated member name `m`. Assume that `m` is +/// a static member declared by `D`. The static analysis and dynamic semantics +/// of this expression is the same as in Dart before the introduction of this +/// feature. +/// ... +/// Assume that it is an extension `E` that declares a static member named `m`. +/// The invocation is then treated as `E.m()`. +/// +/// @description Checks that invocation of `m` is then treated as `E.m()`. Test +/// a static getter as `m`. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +import '../../Utils/expect.dart'; + +String log = ""; + +class C {} + +mixin M {} + +extension type ET(int _) {} + +enum E { + e0; +} + +extension ExtC on C { + static void set foo(String v) { + log = v; + } +} + +extension ExtM on M { + static void set foo(String v) { + log = v; + } +} + +extension ExtET on ET { + static void set foo(String v) { + log = v; + } +} + +extension ExtE on E { + static void set foo(String v) { + log = v; + } +} + +main() { + C.foo = "ExtC"; + Expect.equals("ExtC", log); + M.foo = "ExtM"; + Expect.equals("ExtM", log); + ET.foo = "ExtET"; + Expect.equals("ExtET", log); + E.foo = "ExtE"; + Expect.equals("ExtE", log); + + ExtC.foo = "ExtC"; + Expect.equals("ExtC", log); + ExtM.foo = "ExtM"; + Expect.equals("ExtM", log); + ExtET.foo = "ExtET"; + Expect.equals("ExtET", log); + ExtE.foo = "ExtE"; + Expect.equals("ExtE", log); +} From 2a07008aeeb92f2de279bd0d6b8c07f875b54ce9 Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Wed, 5 Nov 2025 18:11:51 +0200 Subject: [PATCH 2/3] Implement review recommendations --- .../Static-extensions/static_member_A03_t01.dart | 6 +++--- .../Static-extensions/static_member_A03_t02.dart | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/LanguageFeatures/Static-extensions/static_member_A03_t01.dart b/LanguageFeatures/Static-extensions/static_member_A03_t01.dart index f1929a12fa..266fe8d860 100644 --- a/LanguageFeatures/Static-extensions/static_member_A03_t01.dart +++ b/LanguageFeatures/Static-extensions/static_member_A03_t01.dart @@ -8,9 +8,9 @@ /// of this expression is the same as in Dart before the introduction of this /// feature. /// -/// @description Checks that if `C` contains static member with the basename `m` -/// then it is not an error for extensions to declare a static members with the -/// same basename. Invocation of `m` will invoke the appropriate member. +/// @description Checks that if `C` contains a static member with the basename +/// `m` then it is not an error for extensions to declare a static member with +/// the same basename. Invocation of `m` will invoke the `on` declaration member /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=static-extensions diff --git a/LanguageFeatures/Static-extensions/static_member_A03_t02.dart b/LanguageFeatures/Static-extensions/static_member_A03_t02.dart index 47634cbbd8..825ba011b2 100644 --- a/LanguageFeatures/Static-extensions/static_member_A03_t02.dart +++ b/LanguageFeatures/Static-extensions/static_member_A03_t02.dart @@ -8,10 +8,9 @@ /// of this expression is the same as in Dart before the introduction of this /// feature. /// -/// @description Checks that if `C` contains an instance member with the -/// basename `m` then it is not an error for extensions to declare a static -/// member with the same basename. Invocation of `m` will invoke the appropriate -/// member. +/// @description Checks that if `C` contains a static member with the basename +/// `m` then it is not an error for extensions to declare a static member with +/// the same basename. Invocation of `m` will invoke the `on` declaration member /// @author sgrekhov22@gmail.com // SharedOptions=--enable-experiment=static-extensions From 8796d03eb617b858fc67b5559153b7622391a12c Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Fri, 7 Nov 2025 16:51:49 +0200 Subject: [PATCH 3/3] Implement review recommendations 2 --- .../static_member_A04_t01.dart | 6 +- .../static_member_A04_t02.dart | 72 +++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 LanguageFeatures/Static-extensions/static_member_A04_t02.dart diff --git a/LanguageFeatures/Static-extensions/static_member_A04_t01.dart b/LanguageFeatures/Static-extensions/static_member_A04_t01.dart index f203e819ec..f63b4d3556 100644 --- a/LanguageFeatures/Static-extensions/static_member_A04_t01.dart +++ b/LanguageFeatures/Static-extensions/static_member_A04_t01.dart @@ -33,7 +33,7 @@ extension type ET(int _) { enum E { e0; - static void set foo(int _) {} + static int foo() => 42; } extension ExtC on C { @@ -49,7 +49,7 @@ extension ExtET on ET { } extension ExtE on E { - static int get foo => 42; + static void set foo(int _) {} } main() { @@ -65,7 +65,7 @@ main() { // ^^^ // [analyzer] unspecified // [cfe] unspecified - E.foo; + E.foo = 42; // ^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/LanguageFeatures/Static-extensions/static_member_A04_t02.dart b/LanguageFeatures/Static-extensions/static_member_A04_t02.dart new file mode 100644 index 0000000000..2253999b46 --- /dev/null +++ b/LanguageFeatures/Static-extensions/static_member_A04_t02.dart @@ -0,0 +1,72 @@ +// 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 Consider an expression `e` which is a member invocation with +/// syntactic receiver `C` and an associated member name `m`. Assume that `m` is +/// a static member declared by `D`. The static analysis and dynamic semantics +/// of this expression is the same as in Dart before the introduction of this +/// feature. +/// ... +/// When `D` declares a static member whose basename is the basename of `m`, but +/// `D` does not declare a static member named `m` or a constructor named `C.m`, +/// a compile-time error occurs. +/// +/// @description Checks that it is a compile-time error if `D` declares a static +/// member whose basename is the basename of `m`, but `D` does not declare a +/// member named `m` +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=static-extensions + +class C { + static void set foo(int _) {} +} + +mixin M { + static void set foo(int _) {} +} + +extension type ET(int _) { + static void set foo(int _) {} +} + +enum E { + e0; + static void set foo(int _) {} +} + +extension ExtC on C { + static final int foo = 42; +} + +extension ExtM on M { + static int foo() => 42; +} + +extension ExtET on ET { + static int get foo => 42; +} + +extension ExtE on E { + static int get foo => 42; +} + +main() { + C.foo; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified + M.foo(); +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified + ET.foo; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified + E.foo; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified +}