From 1de898c9015b8fb9c3fcf1619d5841d3f022e51b Mon Sep 17 00:00:00 2001 From: "Sergey G. Grekhov" Date: Wed, 11 Oct 2023 14:43:50 +0300 Subject: [PATCH] #2275. Add `noSuchMethod` tests. Part 3 (#2294) Add `noSuchMethod` tests. Part 3 --- .../default_value_A01_t01.dart | 89 +++++++++++ .../default_value_A01_t02.dart | 89 +++++++++++ .../definition_A03_t01.dart | 47 ++++++ .../forwarder_A01_t06.dart | 105 +++++++++++++ .../forwarder_A01_t07.dart | 147 ++++++++++++++++++ .../forwarder_A01_t08.dart | 104 +++++++++++++ .../forwarder_A01_t09.dart | 136 ++++++++++++++++ .../forwarder_A04_t01.dart | 84 ++++++++++ .../invocation_A01_t01.dart | 75 +++++++++ .../invocation_A02_t01.dart | 125 +++++++++++++++ .../invocation_A02_t02.dart | 120 ++++++++++++++ .../invocation_A02_t03.dart | 132 ++++++++++++++++ .../invocation_A02_t04.dart | 113 ++++++++++++++ .../invocation_A02_t05.dart | 60 +++++++ .../invocation_A04_t01.dart | 55 +++++++ 15 files changed, 1481 insertions(+) create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/default_value_A01_t01.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/default_value_A01_t02.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A03_t01.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t06.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t07.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t08.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t09.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A04_t01.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A01_t01.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t01.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t02.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t03.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t04.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t05.dart create mode 100644 Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A04_t01.dart diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/default_value_A01_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/default_value_A01_t01.dart new file mode 100644 index 0000000000..7930129214 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/default_value_A01_t01.dart @@ -0,0 +1,89 @@ +// Copyright (c) 2023, 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 A noSuchMethod forwarder is a concrete member of C with the +/// signature taken from the interface of C, and with the same default value for +/// each optional parameter +/// +/// @description Checks that `noSuchMethod` forwarder has the correct default +/// value for each optional parameter +/// @author sgrekhov22@gmail.com +/// @issue 53656 + +import "../../../../Utils/expect.dart"; + +String log = ""; + +class C { + int m1(int v, [String s = "s1"]); + + int m2(int v, {String s = "s2"}); + + dynamic noSuchMethod(Invocation inv) { + for (int i = 0; i < inv.positionalArguments.length; i++) { + log += "${inv.positionalArguments[i]};"; + } + for (int i = 0; i < inv.namedArguments.length; i++) { + log += "s=${inv.namedArguments[Symbol("s")]};"; + } + return 42; + } +} + +mixin M { + int m1(int v, [String s = "s1"]); + + int m2(int v, {String s = "s2"}); + + dynamic noSuchMethod(Invocation inv) { + for (int i = 0; i < inv.positionalArguments.length; i++) { + log += "${inv.positionalArguments[i]};"; + } + for (int i = 0; i < inv.namedArguments.length; i++) { + log += "s=${inv.namedArguments[Symbol("s")]};"; + } + return 42; + } +} + +class MA = Object with M; + +enum E { + e1, e2; + int m1(int v, [String s = "s1"]); + + int m2(int v, {String s = "s2"}); + + dynamic noSuchMethod(Invocation inv) { + for (int i = 0; i < inv.positionalArguments.length; i++) { + log += "${inv.positionalArguments[i]};"; + } + for (int i = 0; i < inv.namedArguments.length; i++) { + log += "s=${inv.namedArguments[Symbol("s")]};"; + } + return 42; + } +} + +main() { + C().m1(1); + Expect.equals("1;s1;", log); + log = ""; + C().m2(2); + Expect.equals("2;s=s2;", log); + log = ""; + + MA().m1(1); + Expect.equals("1;s1;", log); + log = ""; + MA().m2(2); + Expect.equals("2;s=s2;", log); + log = ""; + + E.e1.m1(1); + Expect.equals("1;s1;", log); + log = ""; + E.e2.m2(2); + Expect.equals("2;s=s2;", log); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/default_value_A01_t02.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/default_value_A01_t02.dart new file mode 100644 index 0000000000..262ffee75a --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/default_value_A01_t02.dart @@ -0,0 +1,89 @@ +// Copyright (c) 2023, 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 A noSuchMethod forwarder is a concrete member of C with the +/// signature taken from the interface of C, and with the same default value for +/// each optional parameter +/// +/// @description Checks that `noSuchMethod` forwarder has the correct default +/// value for each covariant optional parameter +/// @author sgrekhov22@gmail.com +/// @issue 53656 + +import "../../../../Utils/expect.dart"; + +String log = ""; + +class C { + int m1(int v, [covariant String s = "s1"]); + + int m2(int v, {covariant String s = "s2"}); + + dynamic noSuchMethod(Invocation inv) { + for (int i = 0; i < inv.positionalArguments.length; i++) { + log += "${inv.positionalArguments[i]};"; + } + for (int i = 0; i < inv.namedArguments.length; i++) { + log += "s=${inv.namedArguments[Symbol("s")]};"; + } + return 42; + } +} + +mixin M { + int m1(int v, [covariant String s = "s1"]); + + int m2(int v, {covariant String s = "s2"}); + + dynamic noSuchMethod(Invocation inv) { + for (int i = 0; i < inv.positionalArguments.length; i++) { + log += "${inv.positionalArguments[i]};"; + } + for (int i = 0; i < inv.namedArguments.length; i++) { + log += "s=${inv.namedArguments[Symbol("s")]};"; + } + return 42; + } +} + +class MA = Object with M; + +enum E { + e1, e2; + int m1(int v, [covariant String s = "s1"]); + + int m2(int v, {covariant String s = "s2"}); + + dynamic noSuchMethod(Invocation inv) { + for (int i = 0; i < inv.positionalArguments.length; i++) { + log += "${inv.positionalArguments[i]};"; + } + for (int i = 0; i < inv.namedArguments.length; i++) { + log += "s=${inv.namedArguments[Symbol("s")]};"; + } + return 42; + } +} + +main() { + C().m1(1); + Expect.equals("1;s1;", log); + log = ""; + C().m2(2); + Expect.equals("2;s=s2;", log); + log = ""; + + MA().m1(1); + Expect.equals("1;s1;", log); + log = ""; + MA().m2(2); + Expect.equals("2;s=s2;", log); + log = ""; + + E.e1.m1(1); + Expect.equals("1;s1;", log); + log = ""; + E.e2.m2(2); + Expect.equals("2;s=s2;", log); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A03_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A03_t01.dart new file mode 100644 index 0000000000..fc7b7a8163 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A03_t01.dart @@ -0,0 +1,47 @@ +// Copyright (c) 2023, 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 We say that a class C has a non-trivial `noSuchMethod` if C has a +/// concrete member named noSuchMethod which is distinct from the one declared +/// in the built-in class [Object] +/// +/// Note that it must be a method that accepts one positional argument, in order +/// to correctly override noSuchMethod in Object. For instance, it can have +/// signature noSuchMethod(Invocation i) or +/// noSuchMethod(Object i, [String s = ”]), but not +/// noSuchMethod(Invocation i, String s). This implies that the situation where +/// noSuchMethod is invoked (explicitly or implicitly) with one actual argument +/// cannot fail for the reason that “there is no such method”, such that we +/// would enter an infinite loop trying to invoke noSuchMethod. It is possible, +/// however, to encounter a dynamic error during an invocation of noSuchMethod +/// because the actual argument fails to satisfy a type check, but that +/// situation will give rise to a dynamic type error rather than a repeated +/// attempt to invoke noSuchMethod +/// +/// @description Checks that there is no `noSuchMethod` forwarder if a class +/// doesn't declare a concrete member named `noSuchMethod` +/// @author sgrekhov22@gmail.com + +class C1 { + int m1(); +//^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + dynamic noSuchMethod(Invocation inv); +} + +abstract class A { + int a(); + dynamic noSuchMethod(Invocation inv); +} + +class C2 extends A {} +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + +main() { + print(C1); + print(C2); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t06.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t06.dart new file mode 100644 index 0000000000..efb7b69865 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t06.dart @@ -0,0 +1,105 @@ +// Copyright (c) 2023, 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 Let C be a concrete class, let L be the library that contains the +/// declaration of C, and let m be a name. Then m is noSuchMethod forwarded in C +/// iff one of the following is true: +/// +/// • Requested in program: C has a non-trivial noSuchMethod, the interface of C +/// contains a member signature S named m, and C has no concrete member named m +/// and accessible to L that correctly overrides S (that is, no member named m +/// is declared or inherited by C, or one is inherited, but it does not have the +/// required signature). In this case we also say that S is noSuchMethod +/// forwarded. +/// +/// • Forced by privacy: There exists a direct or indirect superinterface D of C +/// which is declared in a library L2 different from L, the interface of D +/// contains a member signature S named m, m is a private name, and no +/// superclass of C has a concrete member named m accessible to L2 that +/// correctly overrides S. In this case we also say that S is noSuchMethod +/// forwarded. +/// +/// For a concrete class C, a noSuchMethod forwarder is implicitly induced for +/// each member signature which is noSuchMethod forwarded. +/// +/// @description Checks that for a concrete class, a `noSuchMethod` forwarder is +/// implicitly induced for each member signature which is `noSuchMethod` +/// forwarded. Test the case when forwarding is requested in program and `C` has +/// no concrete member named `m`. Test getters +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +abstract mixin class A { + String get a; +} + +class C1 { + String get m; + noSuchMethod(Invocation i) => "C1"; +} + +class C2 extends A { + dynamic noSuchMethod(Invocation i) => "C2"; +} + +class C3 implements A { + dynamic noSuchMethod(Invocation i) => "C3"; +} + +class C4 with A { + dynamic noSuchMethod(Invocation i) => "C4"; +} + +mixin M1 { + String get m; + noSuchMethod(Invocation i) => "M1"; +} + +mixin M2 on A { + dynamic noSuchMethod(Invocation i) => "M2"; +} + +mixin M3 implements A { + dynamic noSuchMethod(Invocation i) => "M3"; +} + +class MA1 = Object with M1; +class MA2 = A with M2; +class MA3 = A with M3; + +enum E1 { + e1, + e2; + + String get m; + noSuchMethod(Invocation i) => "E1"; +} + +enum E2 implements A { + e1, + e2; + + dynamic noSuchMethod(Invocation i) => "E2"; +} + +enum E3 with A { + e1, + e2; + + dynamic noSuchMethod(Invocation i) => "E3"; +} + +main() { + Expect.equals("C1", C1().m); + Expect.equals("C2", C2().a); + Expect.equals("C3", C3().a); + Expect.equals("C4", C4().a); + Expect.equals("M1", MA1().m); + Expect.equals("M2", MA2().a); + Expect.equals("M3", MA3().a); + Expect.equals("E1", E1.e1.m); + Expect.equals("E2", E2.e1.a); + Expect.equals("E3", E3.e1.a); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t07.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t07.dart new file mode 100644 index 0000000000..015de6380e --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t07.dart @@ -0,0 +1,147 @@ +// Copyright (c) 2023, 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 Let C be a concrete class, let L be the library that contains the +/// declaration of C, and let m be a name. Then m is noSuchMethod forwarded in C +/// iff one of the following is true: +/// +/// • Requested in program: C has a non-trivial noSuchMethod, the interface of C +/// contains a member signature S named m, and C has no concrete member named m +/// and accessible to L that correctly overrides S (that is, no member named m +/// is declared or inherited by C, or one is inherited, but it does not have the +/// required signature). In this case we also say that S is noSuchMethod +/// forwarded. +/// +/// • Forced by privacy: There exists a direct or indirect superinterface D of C +/// which is declared in a library L2 different from L, the interface of D +/// contains a member signature S named m, m is a private name, and no +/// superclass of C has a concrete member named m accessible to L2 that +/// correctly overrides S. In this case we also say that S is noSuchMethod +/// forwarded. +/// +/// For a concrete class C, a noSuchMethod forwarder is implicitly induced for +/// each member signature which is noSuchMethod forwarded. +/// +/// @description Checks that for a concrete class, a `noSuchMethod` forwarder is +/// implicitly induced for each member signature which is `noSuchMethod` +/// forwarded. Test the case when forwarding is requested in program and `C` has +/// no concrete member named `m`. Test setters +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +String log = ""; + +abstract mixin class A { + void set a(String s); +} + +class C1 { + void set m(String s); + noSuchMethod(Invocation i) { + log = "C1"; + } +} + +class C2 extends A { + dynamic noSuchMethod(Invocation i) { + log = "C2"; + } +} + +class C3 implements A { + dynamic noSuchMethod(Invocation i) { + log = "C3"; + } +} + +class C4 with A { + dynamic noSuchMethod(Invocation i) { + log = "C4"; + } +} + +mixin M1 { + void set m(String s); + noSuchMethod(Invocation i) { + log = "M1"; + } +} + +mixin M2 on A { + dynamic noSuchMethod(Invocation i) { + log = "M2"; + } +} + +mixin M3 implements A { + dynamic noSuchMethod(Invocation i) { + log = "M3"; + } +} + +class MA1 = Object with M1; +class MA2 = A with M2; +class MA3 = A with M3; + +enum E1 { + e1, + e2; + + void set m(String s); + noSuchMethod(Invocation i) { + log = "E1"; + } +} + +enum E2 implements A { + e1, + e2; + + dynamic noSuchMethod(Invocation i) { + log = "E2"; + } +} + +enum E3 with A { + e1, + e2; + + dynamic noSuchMethod(Invocation i) { + log = "E3"; + } +} + +main() { + C1().m = ""; + Expect.equals("C1", log); + log = ""; + C2().a = ""; + Expect.equals("C2", log); + log = ""; + C3().a = ""; + Expect.equals("C3", log); + log = ""; + C4().a = ""; + Expect.equals("C4", log); + log = ""; + MA1().m = ""; + Expect.equals("M1", log); + log = ""; + MA2().a = ""; + Expect.equals("M2", log); + log = ""; + MA3().a = ""; + Expect.equals("M3", log); + log = ""; + E1.e1.m = ""; + Expect.equals("E1", log); + log = ""; + E2.e1.a = ""; + Expect.equals("E2", log); + log = ""; + E3.e1.a = ""; + Expect.equals("E3", log); + log = ""; +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t08.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t08.dart new file mode 100644 index 0000000000..a98816b633 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t08.dart @@ -0,0 +1,104 @@ +// Copyright (c) 2023, 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 Let C be a concrete class, let L be the library that contains the +/// declaration of C, and let m be a name. Then m is noSuchMethod forwarded in C +/// iff one of the following is true: +/// +/// • Requested in program: C has a non-trivial noSuchMethod, the interface of C +/// contains a member signature S named m, and C has no concrete member named m +/// and accessible to L that correctly overrides S (that is, no member named m +/// is declared or inherited by C, or one is inherited, but it does not have the +/// required signature). In this case we also say that S is noSuchMethod +/// forwarded. +/// +/// • Forced by privacy: There exists a direct or indirect superinterface D of C +/// which is declared in a library L2 different from L, the interface of D +/// contains a member signature S named m, m is a private name, and no +/// superclass of C has a concrete member named m accessible to L2 that +/// correctly overrides S. In this case we also say that S is noSuchMethod +/// forwarded. +/// +/// For a concrete class C, a noSuchMethod forwarder is implicitly induced for +/// each member signature which is noSuchMethod forwarded. +/// +/// @description Checks that for a concrete class, a `noSuchMethod` forwarder is +/// invoked if `C` has no concrete member named `m`. Expect run-time error if a +/// forwarder returns not expected run-time type. Test getters +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +abstract mixin class A { + String get a; +} + +class C1 { + String get m; + noSuchMethod(Invocation i) => 1; +} + +class C2 extends A { + dynamic noSuchMethod(Invocation i) => 2; +} + +class C3 implements A { + dynamic noSuchMethod(Invocation i) => 3; +} + +class C4 with A { + dynamic noSuchMethod(Invocation i) => 4; +} + +mixin M1 { + String get m; + noSuchMethod(Invocation i) => 11; +} + +mixin M2 on A { + dynamic noSuchMethod(Invocation i) => 12; +} + +mixin M3 implements A { + dynamic noSuchMethod(Invocation i) => 13; +} + +class MA1 = Object with M1; +class MA2 = A with M2; +class MA3 = A with M3; + +enum E1 { + e1, + e2; + + String get m; + noSuchMethod(Invocation i) => 21; +} + +enum E2 implements A { + e1, + e2; + + dynamic noSuchMethod(Invocation i) => 22; +} + +enum E3 with A { + e1, + e2; + + dynamic noSuchMethod(Invocation i) => 23; +} + +main() { + Expect.throws(() {C1().m;}, (e) => e is TypeError); + Expect.throws(() {C2().a;}, (e) => e is TypeError); + Expect.throws(() {C3().a;}, (e) => e is TypeError); + Expect.throws(() {C4().a;}, (e) => e is TypeError); + Expect.throws(() {MA1().m;}, (e) => e is TypeError); + Expect.throws(() {MA2().a;}, (e) => e is TypeError); + Expect.throws(() {MA3().a;}, (e) => e is TypeError); + Expect.throws(() {E1.e1.m;}, (e) => e is TypeError); + Expect.throws(() {E2.e1.a;}, (e) => e is TypeError); + Expect.throws(() {E3.e1.a;}, (e) => e is TypeError); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t09.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t09.dart new file mode 100644 index 0000000000..003c98fbf2 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t09.dart @@ -0,0 +1,136 @@ +// Copyright (c) 2023, 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 Let C be a concrete class, let L be the library that contains the +/// declaration of C, and let m be a name. Then m is noSuchMethod forwarded in C +/// iff one of the following is true: +/// +/// • Requested in program: C has a non-trivial noSuchMethod, the interface of C +/// contains a member signature S named m, and C has no concrete member named m +/// and accessible to L that correctly overrides S (that is, no member named m +/// is declared or inherited by C, or one is inherited, but it does not have the +/// required signature). In this case we also say that S is noSuchMethod +/// forwarded. +/// +/// • Forced by privacy: There exists a direct or indirect superinterface D of C +/// which is declared in a library L2 different from L, the interface of D +/// contains a member signature S named m, m is a private name, and no +/// superclass of C has a concrete member named m accessible to L2 that +/// correctly overrides S. In this case we also say that S is noSuchMethod +/// forwarded. +/// +/// For a concrete class C, a noSuchMethod forwarder is implicitly induced for +/// each member signature which is noSuchMethod forwarded. +/// +/// @description Checks that for a concrete class, a `noSuchMethod` forwarder is +/// invoked if `C` has no concrete member named `m`. Expect run-time error if a +/// forwarder of a setter is called with a wrong type. +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +String log = ""; + +abstract mixin class A { + void set a(String s); +} + +class C1 { + void set m(String s); + noSuchMethod(Invocation i) { + log = "C1"; + } +} + +class C2 extends A { + dynamic noSuchMethod(Invocation i) { + log = "C2"; + } +} + +class C3 implements A { + dynamic noSuchMethod(Invocation i) { + log = "C3"; + } +} + +class C4 with A { + dynamic noSuchMethod(Invocation i) { + log = "C4"; + } +} + +mixin M1 { + void set m(String s); + noSuchMethod(Invocation i) { + log = "M1"; + } +} + +mixin M2 on A { + dynamic noSuchMethod(Invocation i) { + log = "M2"; + } +} + +mixin M3 implements A { + dynamic noSuchMethod(Invocation i) { + log = "M3"; + } +} + +class MA1 = Object with M1; +class MA2 = A with M2; +class MA3 = A with M3; + +enum E1 { + e1, + e2; + + void set m(String s); + noSuchMethod(Invocation i) { + log = "E1"; + } +} + +enum E2 implements A { + e1, + e2; + + dynamic noSuchMethod(Invocation i) { + log = "E2"; + } +} + +enum E3 with A { + e1, + e2; + + dynamic noSuchMethod(Invocation i) { + log = "E3"; + } +} + +main() { + Expect.throws(() {(C1() as dynamic).m = 1;}, (e) => e is TypeError); + Expect.equals("", log); + Expect.throws(() {(C2() as dynamic).a = 2;}, (e) => e is TypeError); + Expect.equals("", log); + Expect.throws(() {(C3() as dynamic).a = 3;}, (e) => e is TypeError); + Expect.equals("", log); + Expect.throws(() {(C4() as dynamic).a = 4;}, (e) => e is TypeError); + Expect.equals("", log); + Expect.throws(() {(MA1() as dynamic).m = 11;}, (e) => e is TypeError); + Expect.equals("", log); + Expect.throws(() {(MA2() as dynamic).a = 12;}, (e) => e is TypeError); + Expect.equals("", log); + Expect.throws(() {(MA3() as dynamic).a = 13;}, (e) => e is TypeError); + Expect.equals("", log); + Expect.throws(() {(E1.e1 as dynamic).m = 21;}, (e) => e is TypeError); + Expect.equals("", log); + Expect.throws(() {(E2.e2 as dynamic).a = 22;}, (e) => e is TypeError); + Expect.equals("", log); + Expect.throws(() {(E3.e1 as dynamic).a = 23;}, (e) => e is TypeError); + Expect.equals("", log); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A04_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A04_t01.dart new file mode 100644 index 0000000000..5def95499d --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A04_t01.dart @@ -0,0 +1,84 @@ +// Copyright (c) 2023, 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 Let C be a concrete class, let L be the library that contains the +/// declaration of C, and let m be a name. Then m is noSuchMethod forwarded in C +/// iff one of the following is true: +/// +/// • Requested in program: C has a non-trivial noSuchMethod, the interface of C +/// contains a member signature S named m, and C has no concrete member named m +/// and accessible to L that correctly overrides S (that is, no member named m +/// is declared or inherited by C, or one is inherited, but it does not have the +/// required signature). In this case we also say that S is noSuchMethod +/// forwarded. +/// +/// • Forced by privacy: There exists a direct or indirect superinterface D of C +/// which is declared in a library L2 different from L, the interface of D +/// contains a member signature S named m, m is a private name, and no +/// superclass of C has a concrete member named m accessible to L2 that +/// correctly overrides S. In this case we also say that S is noSuchMethod +/// forwarded. +/// +/// For a concrete class C, a noSuchMethod forwarder is implicitly induced for +/// each member signature which is noSuchMethod forwarded. +/// +/// @description Checks that there is no 'noSuchMethod' forwarder if class `C` +/// is not a concrete class. +/// @author sgrekhov22@gmail.com + +abstract mixin class A { + int m1(int v, [covariant String s = "s1"]); + + int m2(int v, {covariant String s = "s2"}); + + dynamic noSuchMethod(Invocation inv) { + return 42; + } +} + +class C1 extends A { + test() { + super.m1(1, "1"); +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + super.m2(2, s: "2"); +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + } +} + +class C2 with A { + test() { + super.m1(1, "1"); +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + super.m2(2, s: "2"); +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + } +} + +enum E with A { + e1, e2; + test() { + super.m1(1, "1"); +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + super.m2(2, s: "2"); +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + } +} + +main() { + print(C1); + print(C2); + print(E); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A01_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A01_t01.dart new file mode 100644 index 0000000000..05249e3a1d --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A01_t01.dart @@ -0,0 +1,75 @@ +// Copyright (c) 2023, 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 A noSuchMethod forwarder is a concrete member of C with the +/// signature taken from the interface of C, and with the same default value for +/// each optional parameter. It can be invoked in an ordinary invocation and in +/// a superinvocation, and when m is a method it can be closurized using a +/// property extraction. +/// +/// @description Checks that `noSuchMethod` forwarder can be invoked in an +/// ordinary invocation and in a superinvocation +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +mixin class A { + int m1(int v, [covariant String s = "s1"]); + + int m2(int v, {covariant String s = "s2"}); + + dynamic noSuchMethod(Invocation inv) { + return 42; + } +} + +class C1 extends A { + test() { + Expect.equals(42, super.m1(1, "1")); + Expect.equals(42, super.m2(2, s: "2")); + Expect.equals(42, this.m1(1, "1")); + Expect.equals(42, this.m2(2, s: "2")); + } +} + +class C2 with A { + test() { + // Superclass of `C2 with A` is abstract, so there is no `super.m1/m2()` + Expect.equals(42, this.m1(1, "1")); + Expect.equals(42, this.m2(2, s: "2")); + } +} + +mixin M on A { + test() { + Expect.equals(42, super.m1(1, "1")); + Expect.equals(42, super.m2(2, s: "2")); + Expect.equals(42, this.m1(1, "1")); + Expect.equals(42, this.m2(2, s: "2")); + } +} + +class MA = A with M; + +enum E with A { + e1, e2; + test() { + // Superclass of `E with A` is abstract, so there is no `super.m1/m2()` + Expect.equals(42, this.m1(1, "1")); + Expect.equals(42, this.m2(2, s: "2")); + } +} + +main() { + Expect.equals(42, A().m1(1, "1")); + Expect.equals(42, A().m2(2, s: "2")); + C1().test(); + C2().test(); + Expect.equals(42, MA().m1(1, "1")); + Expect.equals(42, MA().m2(2, s: "2")); + MA().test(); + Expect.equals(42, E.e1.m1(1, "1")); + Expect.equals(42, E.e1.m2(2, s: "2")); + E.e1.test(); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t01.dart new file mode 100644 index 0000000000..76f368dece --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t01.dart @@ -0,0 +1,125 @@ +// Copyright (c) 2023, 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 A noSuchMethod forwarder is a concrete member of C with the +/// signature taken from the interface of C, and with the same default value for +/// each optional parameter. It can be invoked in an ordinary invocation and in +/// a superinvocation, and when m is a method it can be closurized using a +/// property extraction. +/// +/// @description Checks that when a `noSuchMethod` forwarder is a method it can +/// be closurized using a property extraction +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; +import "../../../../Utils/static_type_helper.dart"; + +mixin class A { + int m1(int v, [String s = "s1"]); + + int m2(int v, {String s}); + + int m3(int v, {required String s}); + + int m4(int v, [covariant String s]); + + dynamic noSuchMethod(Invocation inv) { + return 42; + } +} + +class C1 extends A {} + +class C2 with A {} + +mixin M on A {} + +class MA = A with M; + +enum E with A { + e1, e2; +} + +main() { + var a1 = A().m1; + a1.expectStaticType>(); + Expect.equals(42, a1(1, "1")); + + var a2 = A().m2; + a2.expectStaticType>(); + Expect.equals(42, a2(1, s: "1")); + + var a3 = A().m3; + a3.expectStaticType>(); + Expect.equals(42, a3(1, s: "1")); + + var a4 = A().m4; + a4.expectStaticType>(); + Expect.equals(42, a4(1, "1")); + + var c11 = C1().m1; + c11.expectStaticType>(); + Expect.equals(42, c11(1, "1")); + + var c12 = C1().m2; + c12.expectStaticType>(); + Expect.equals(42, c12(1, s: "1")); + + var c13 = C1().m3; + c13.expectStaticType>(); + Expect.equals(42, c13(1, s: "1")); + + var c14 = C1().m4; + c14.expectStaticType>(); + Expect.equals(42, c14(1, "1")); + + var c21 = C2().m1; + c21.expectStaticType>(); + Expect.equals(42, c21(1, "1")); + + var c22 = C2().m2; + c22.expectStaticType>(); + Expect.equals(42, c22(1, s: "1")); + + var c23 = C2().m3; + c23.expectStaticType>(); + Expect.equals(42, c23(1, s: "1")); + + var c24 = C2().m4; + c24.expectStaticType>(); + Expect.equals(42, c24(1, "1")); + + var m1 = MA().m1; + m1.expectStaticType>(); + Expect.equals(42, m1(1, "1")); + + var m2 = MA().m2; + m2.expectStaticType>(); + Expect.equals(42, m2(1, s: "1")); + + var m3 = MA().m3; + m3.expectStaticType>(); + Expect.equals(42, m3(1, s: "1")); + + var m4 = MA().m4; + m4.expectStaticType>(); + Expect.equals(42, m4(1, "1")); + + var e1 = E.e1.m1; + e1.expectStaticType>(); + Expect.equals(42, e1(1, "1")); + + var e2 = E.e2.m2; + e2.expectStaticType>(); + Expect.equals(42, e2(1, s: "1")); + + var e3 = E.e1.m3; + e3.expectStaticType>(); + Expect.equals(42, e3(1, s: "1")); + + var e4 = E.e2.m4; + e4.expectStaticType>(); + Expect.equals(42, e4(1, "1")); + +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t02.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t02.dart new file mode 100644 index 0000000000..1b83d95b0d --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t02.dart @@ -0,0 +1,120 @@ +// Copyright (c) 2023, 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 A noSuchMethod forwarder is a concrete member of C with the +/// signature taken from the interface of C, and with the same default value for +/// each optional parameter. It can be invoked in an ordinary invocation and in +/// a superinvocation, and when m is a method it can be closurized using a +/// property extraction. +/// +/// @description Checks that when a `noSuchMethod` forwarder is a method it can +/// be closurized using a property extraction +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; +import "../../../../Utils/static_type_helper.dart"; + +abstract mixin class A { + String m1(int v, [String s = "s1"]); + + String m2(int v, {String s}); + + String m3(int v, {required String s}); + + String m4(int v, [covariant String s]); +} + +class C1 extends A { + dynamic noSuchMethod(Invocation inv) { + return "C1"; + } +} + +class C2 with A { + dynamic noSuchMethod(Invocation inv) { + return "C2"; + } +} + +mixin M on A { + dynamic noSuchMethod(Invocation inv) { + return "M"; + } +} + +class MA = A with M; + +enum E with A { + e1, e2; + dynamic noSuchMethod(Invocation inv) { + return "E"; + } +} + +main() { + var c11 = C1().m1; + c11.expectStaticType>(); + Expect.equals("C1", c11(1, "1")); + + var c12 = C1().m2; + c12.expectStaticType>(); + Expect.equals("C1", c12(1, s: "1")); + + var c13 = C1().m3; + c13.expectStaticType>(); + Expect.equals("C1", c13(1, s: "1")); + + var c14 = C1().m4; + c14.expectStaticType>(); + Expect.equals("C1", c14(1, "1")); + + var c21 = C2().m1; + c21.expectStaticType>(); + Expect.equals("C2", c21(1, "1")); + + var c22 = C2().m2; + c22.expectStaticType>(); + Expect.equals("C2", c22(1, s: "1")); + + var c23 = C2().m3; + c23.expectStaticType>(); + Expect.equals("C2", c23(1, s: "1")); + + var c24 = C2().m4; + c24.expectStaticType>(); + Expect.equals("C2", c24(1, "1")); + + var m1 = MA().m1; + m1.expectStaticType>(); + Expect.equals("M", m1(1, "1")); + + var m2 = MA().m2; + m2.expectStaticType>(); + Expect.equals("M", m2(1, s: "1")); + + var m3 = MA().m3; + m3.expectStaticType>(); + Expect.equals("M", m3(1, s: "1")); + + var m4 = MA().m4; + m4.expectStaticType>(); + Expect.equals("M", m4(1, "1")); + + var e1 = E.e1.m1; + e1.expectStaticType>(); + Expect.equals("E", e1(1, "1")); + + var e2 = E.e2.m2; + e2.expectStaticType>(); + Expect.equals("E", e2(1, s: "1")); + + var e3 = E.e1.m3; + e3.expectStaticType>(); + Expect.equals("E", e3(1, s: "1")); + + var e4 = E.e2.m4; + e4.expectStaticType>(); + Expect.equals("E", e4(1, "1")); + +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t03.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t03.dart new file mode 100644 index 0000000000..415a7b8989 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t03.dart @@ -0,0 +1,132 @@ +// Copyright (c) 2023, 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 A noSuchMethod forwarder is a concrete member of C with the +/// signature taken from the interface of C, and with the same default value for +/// each optional parameter. It can be invoked in an ordinary invocation and in +/// a superinvocation, and when m is a method it can be closurized using a +/// property extraction. +/// +/// @description Checks that when a `noSuchMethod` forwarder is a method it can +/// be closurized using a property extraction +/// @author sgrekhov22@gmail.com +/// @issue 53677 + +import "../../../../Utils/expect.dart"; +import "../../../../Utils/static_type_helper.dart"; + +mixin class A { + dynamic noSuchMethod(Invocation inv) { + return "A"; + } +} + +class C1 extends A { + String m1(int v, [String s = "s1"]); + + String m2(int v, {String s}); + + String m3(int v, {required String s}); + + String m4(int v, [covariant String s]); +} + +class C2 with A { + String m1(int v, [String s = "s1"]); + + String m2(int v, {String s}); + + String m3(int v, {required String s}); + + String m4(int v, [covariant String s]); +} + +mixin M on A { + String m1(int v, [String s = "s1"]); + + String m2(int v, {String s}); + + String m3(int v, {required String s}); + + String m4(int v, [covariant String s]); +} + +class MA = A with M; + +enum E with A { + e1, e2; + String m1(int v, [String s = "s1"]); + + String m2(int v, {String s}); + + String m3(int v, {required String s}); + + String m4(int v, [covariant String s]); +} + +main() { + var c11 = C1().m1; + c11.expectStaticType>(); + Expect.equals("A", c11(1, "1")); + + var c12 = C1().m2; + c12.expectStaticType>(); + Expect.equals("A", c12(1, s: "1")); + + var c13 = C1().m3; + c13.expectStaticType>(); + Expect.equals("A", c13(1, s: "1")); + + var c14 = C1().m4; + c14.expectStaticType>(); + Expect.equals("A", c14(1, "1")); + + var c21 = C2().m1; + c21.expectStaticType>(); + Expect.equals("A", c21(1, "1")); + + var c22 = C2().m2; + c22.expectStaticType>(); + Expect.equals("A", c22(1, s: "1")); + + var c23 = C2().m3; + c23.expectStaticType>(); + Expect.equals("A", c23(1, s: "1")); + + var c24 = C2().m4; + c24.expectStaticType>(); + Expect.equals("A", c24(1, "1")); + + var m1 = MA().m1; + m1.expectStaticType>(); + Expect.equals("A", m1(1, "1")); + + var m2 = MA().m2; + m2.expectStaticType>(); + Expect.equals("A", m2(1, s: "1")); + + var m3 = MA().m3; + m3.expectStaticType>(); + Expect.equals("A", m3(1, s: "1")); + + var m4 = MA().m4; + m4.expectStaticType>(); + Expect.equals("A", m4(1, "1")); + + var e1 = E.e1.m1; + e1.expectStaticType>(); + Expect.equals("A", e1(1, "1")); + + var e2 = E.e2.m2; + e2.expectStaticType>(); + Expect.equals("A", e2(1, s: "1")); + + var e3 = E.e1.m3; + e3.expectStaticType>(); + Expect.equals("A", e3(1, s: "1")); + + var e4 = E.e2.m4; + e4.expectStaticType>(); + Expect.equals("A", e4(1, "1")); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t04.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t04.dart new file mode 100644 index 0000000000..dfdea2c43f --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t04.dart @@ -0,0 +1,113 @@ +// Copyright (c) 2023, 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 A noSuchMethod forwarder is a concrete member of C with the +/// signature taken from the interface of C, and with the same default value for +/// each optional parameter. It can be invoked in an ordinary invocation and in +/// a superinvocation, and when m is a method it can be closurized using a +/// property extraction. +/// +/// @description Checks that when a `noSuchMethod` forwarder is a method it can +/// be closurized using a property extraction +/// @author sgrekhov22@gmail.com +/// @issue 53677 + +import "../../../../Utils/expect.dart"; +import "../../../../Utils/static_type_helper.dart"; + +class C { + String m1(int v, [String s = "s1"]); + + String m2(int v, {String s}); + + String m3(int v, {required String s}); + + String m4(int v, [covariant String s]); + + dynamic noSuchMethod(Invocation inv) { + return "C1"; + } +} + +mixin M { + String m1(int v, [String s = "s1"]); + + String m2(int v, {String s}); + + String m3(int v, {required String s}); + + String m4(int v, [covariant String s]); + + dynamic noSuchMethod(Invocation inv) { + return "M"; + } +} + +class MA = Object with M; + +enum E { + e1, e2; + String m1(int v, [String s = "s1"]); + + String m2(int v, {String s}); + + String m3(int v, {required String s}); + + String m4(int v, [covariant String s]); + + dynamic noSuchMethod(Invocation inv) { + return "E"; + } +} + +main() { + var c1 = C().m1; + c1.expectStaticType>(); + Expect.equals("C1", c1(1, "1")); + + var c2 = C().m2; + c2.expectStaticType>(); + Expect.equals("C1", c2(1, s: "1")); + + var c3 = C().m3; + c3.expectStaticType>(); + Expect.equals("C1", c3(1, s: "1")); + + var c4 = C().m4; + c4.expectStaticType>(); + Expect.equals("C1", c4(1, "1")); + + var m1 = MA().m1; + m1.expectStaticType>(); + Expect.equals("M", m1(1, "1")); + + var m2 = MA().m2; + m2.expectStaticType>(); + Expect.equals("M", m2(1, s: "1")); + + var m3 = MA().m3; + m3.expectStaticType>(); + Expect.equals("M", m3(1, s: "1")); + + var m4 = MA().m4; + m4.expectStaticType>(); + Expect.equals("M", m4(1, "1")); + + var e1 = E.e1.m1; + e1.expectStaticType>(); + Expect.equals("E", e1(1, "1")); + + var e2 = E.e2.m2; + e2.expectStaticType>(); + Expect.equals("E", e2(1, s: "1")); + + var e3 = E.e1.m3; + e3.expectStaticType>(); + Expect.equals("E", e3(1, s: "1")); + + var e4 = E.e2.m4; + e4.expectStaticType>(); + Expect.equals("E", e4(1, "1")); + +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t05.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t05.dart new file mode 100644 index 0000000000..55fcea1eed --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A02_t05.dart @@ -0,0 +1,60 @@ +// Copyright (c) 2023, 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 A noSuchMethod forwarder is a concrete member of C with the +/// signature taken from the interface of C, and with the same default value for +/// each optional parameter. It can be invoked in an ordinary invocation and in +/// a superinvocation, and when m is a method it can be closurized using a +/// property extraction. +/// +/// @description Checks that when a `noSuchMethod` forwarder is a setter it +/// cannot be closurized using a property extraction +/// @author sgrekhov22@gmail.com + +mixin class A { + void set m(int v); + + dynamic noSuchMethod(Invocation inv) { + return 42; + } +} + +class C1 extends A {} + +class C2 with A {} + +mixin M on A {} + +class MA = A with M; + +enum E with A { + e1, e2; +} + +main() { + var a1 = A().m; +// ^ +// [analyzer] unspecified +// [cfe] unspecified + + var c1 = C1().m; +// ^ +// [analyzer] unspecified +// [cfe] unspecified + + var c2 = C2().m; +// ^ +// [analyzer] unspecified +// [cfe] unspecified + + var m1 = MA().m; +// ^ +// [analyzer] unspecified +// [cfe] unspecified + + var e1 = E.e1.m; +// ^ +// [analyzer] unspecified +// [cfe] unspecified +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A04_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A04_t01.dart new file mode 100644 index 0000000000..db1df5ba78 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/invocation_A04_t01.dart @@ -0,0 +1,55 @@ +// Copyright (c) 2023, 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 A noSuchMethod forwarder is a concrete member of C with the +/// signature taken from the interface of C, and with the same default value for +/// each optional parameter. It can be invoked in an ordinary invocation and in +/// a superinvocation, and when m is a method it can be closurized using a +/// property extraction. +/// +/// @description Checks that it is a compile-time error to call a `super.m()` in +/// a mixin application with a no `noSuchMethod` forwarder +/// @author sgrekhov22@gmail.com + +mixin class A { + int m1(int v, [covariant String s = "s1"]); + + int m2(int v, {covariant String s = "s2"}); + + dynamic noSuchMethod(Invocation inv) { + return 42; + } +} + +class C with A { + test() { + super.m1(1, "1"); +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + super.m2(1, s: "1"); +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + } +} + +enum E with A { + e1, e2; + test() { + super.m1(1, "1"); +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + super.m2(1, s: "1"); +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + } +} + +main() { + print(C); + print(E); +}