diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t01.dart new file mode 100644 index 0000000000..0946ce32be --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t01.dart @@ -0,0 +1,65 @@ +// 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 it is possible to define a `noSuchMethod` which +/// is a correct override of `noSuchMethod` in `Object`. +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +class C1 { + int m(); + void noSuchMethod(Invocation i) {} +} + +class C2 { + int m(); + Object? noSuchMethod(Invocation i) => 2; +} + +class C3 { + int m(); + Null noSuchMethod(Invocation i) => null; +} + +class C4 { + int m(); + Never noSuchMethod(Invocation i) => throw 42; +} + +class C5 { + int m(); + int noSuchMethod(Invocation i) => 5; +} + +main() { + Expect.throws(() { + C1().m(); + }); + Expect.equals(2, C2().m()); + Expect.throws(() { + C3().m(); + }); + Expect.throws(() { + C4().m(); + }); + Expect.equals(5, C5().m()); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t02.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t02.dart new file mode 100644 index 0000000000..95e579e5df --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t02.dart @@ -0,0 +1,43 @@ +// 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 it is possible to define a `noSuchMethod` which +/// is a correct override of `noSuchMethod` in `Object`. +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +class C1 { + int m(); + dynamic noSuchMethod(Invocation i, [int x = 1]) { + return x; + } +} + +class C2 { + int m(); + dynamic noSuchMethod(Invocation i, {int x = 2}) => x; +} + +main() { + Expect.equals(1, C1().m()); + Expect.equals(2, C2().m()); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t03.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t03.dart new file mode 100644 index 0000000000..14d9ad519d --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t03.dart @@ -0,0 +1,43 @@ +// 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 it is possible to define a `noSuchMethod` which +/// is a correct override of `noSuchMethod` in `Object`. +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +class C1 { + int m(); + external dynamic noSuchMethod(Invocation i); +} + +class C2 { + int m(); + dynamic noSuchMethod(covariant Invocation i) => 2; +} + +main() { + Expect.throws(() { + C1().m(); + }); + Expect.equals(2, C2().m()); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t04.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t04.dart new file mode 100644 index 0000000000..9d88a1e464 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A01_t04.dart @@ -0,0 +1,37 @@ +// 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 it is possible to define a `noSuchMethod` which +/// is a correct override of `noSuchMethod` in `Object`. +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +class C1 { + int m(); + dynamic noSuchMethod(covariant Object o) => o; +} + +main() { + Expect.throws(() { + C1().m(); + }); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A02_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A02_t01.dart new file mode 100644 index 0000000000..b64c66260f --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A02_t01.dart @@ -0,0 +1,59 @@ +// 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 it is a compile-time error to define a +/// `noSuchMethod` which is not a correct override of `noSuchMethod` in `Object` +/// @author sgrekhov22@gmail.com + +class C1 { + void noSuchMethod() {} +// ^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +class C2 { + void noSuchMethod(Invocation i, String s) {} +// ^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +class C3 { + void noSuchMethod(Invocation i, {required String s}) {} +// ^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +class C4 { + dynamic noSuchMethod(int i) => i; +// ^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + print(C1); + print(C2); + print(C3); + print(C4); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A02_t02.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A02_t02.dart new file mode 100644 index 0000000000..491a8e70ed --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/definition_A02_t02.dart @@ -0,0 +1,59 @@ +// 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 it is a compile-time error to define a +/// `noSuchMethod` which is not a correct override of `noSuchMethod` in `Object` +/// @author sgrekhov22@gmail.com + +class C1 { + external void noSuchMethod(); +// ^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +class C2 { + external void noSuchMethod(Invocation i, String s); +// ^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +class C3 { + external void noSuchMethod(Invocation i, {required String s}); +// ^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +class C4 { + external dynamic noSuchMethod(int i); +// ^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + print(C1); + print(C2); + print(C3); + print(C4); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t01.dart new file mode 100644 index 0000000000..581e5ea0db --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t01.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` +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +abstract mixin class A { + String a(); +} + +class C1 { + String 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 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 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_t02.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t02.dart new file mode 100644 index 0000000000..c7959a2996 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t02.dart @@ -0,0 +1,57 @@ +// 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` +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +abstract mixin class A { + String a(); + noSuchMethod(Invocation i) => "A"; +} + +class C1 extends A {} + +class C2 with A {} + +mixin M on A {} + +class MA = A with M; + +enum E with A { + e1, + e2; +} + +main() { + Expect.equals("A", C1().a()); + Expect.equals("A", C2().a()); + Expect.equals("A", MA().a()); + Expect.equals("A", E.e1.a()); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t03.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t03.dart new file mode 100644 index 0000000000..83cb917f76 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t03.dart @@ -0,0 +1,73 @@ +// 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` +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +abstract mixin class A { + String a(); +} + +mixin class B { + noSuchMethod(Invocation i) => "B"; +} + +class C1 extends A with B {} + +class C2 extends B with A {} + +class C3 extends B implements A {} + +class C4 with B implements A {} + +class C5 with A, B {} + +mixin M on B implements A {} + +class MB = B with M; + +enum E1 with B implements A { + e1, e2; +} + +enum E2 with A, B { + e1, e2; +} + +main() { + Expect.equals("B", C1().a()); + Expect.equals("B", C2().a()); + Expect.equals("B", C3().a()); + Expect.equals("B", C4().a()); + Expect.equals("B", C5().a()); + Expect.equals("B", MB().a()); + Expect.equals("B", E1.e1.a()); + Expect.equals("B", E2.e1.a()); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t04.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t04.dart new file mode 100644 index 0000000000..7cca7871c2 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A01_t04.dart @@ -0,0 +1,91 @@ +// 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 it is a compile-time error if a class or enum +/// doesn't have a non-trivial `noSuchMethod` instance method, and has a member +/// without an implementation +/// @author sgrekhov22@gmail.com + +abstract mixin class A { + String a(); +} + +mixin class B { + noSuchMethod(Invocation i) => "B"; +} + +abstract class D { + String d(); + noSuchMethod(Invocation i) => "D"; +} + +class C1 implements D { +// ^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +class C2 implements A, B { +// ^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +mixin M on A implements B {} + +class MA = A with M; +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + +enum E1 implements D { +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + e1, e2; +} + +enum E2 implements A, B { +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + e1, e2; +} + +enum E3 with A implements B { +// ^^ +// [analyzer] unspecified +// [cfe] unspecified +e1, e2; +} + +main() { + print(C1); + print(C2); + print(MA); + print(E1); + print(E2); + print(E3); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A02_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A02_t01.dart new file mode 100644 index 0000000000..fd9fab1396 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A02_t01.dart @@ -0,0 +1,72 @@ +// 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 +/// a concrete member named `m` but it doesn't have a required signature +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +abstract mixin class A { + String m([String s]); +} + +class B { + String m() => "B"; +} + +class C1 extends A implements B { + dynamic noSuchMethod(Invocation i) => "C1"; +} + +class C2 with A implements B { + dynamic noSuchMethod(Invocation i) => "C2"; +} + +mixin M on A implements B { + dynamic noSuchMethod(Invocation i) => "M"; +} + +class MA = A with M; + +enum E with A implements B { + e1, + e2; + + noSuchMethod(Invocation i) => "E"; +} + +main() { + Expect.equals("C1", C1().m()); + Expect.equals("C1", C1().m("")); + Expect.equals("C2", C2().m()); + Expect.equals("C2", C2().m("")); + Expect.equals("M", MA().m()); + Expect.equals("M", MA().m("")); + Expect.equals("E", E.e1.m()); + Expect.equals("E", E.e1.m("")); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A02_t02.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A02_t02.dart new file mode 100644 index 0000000000..1e35f66144 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A02_t02.dart @@ -0,0 +1,65 @@ +// 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 +/// a concrete member named `m` but it doesn't have a required signature +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +abstract mixin class A { + String m([String s = ""]); + dynamic noSuchMethod(Invocation i) => "A"; +} + +abstract class B { + String m(); +} + +class C1 extends A implements B {} + +class C2 with A implements B {} + +mixin M on A implements B {} + +class MA = A with M; + +enum E with A implements B { + e1, + e2; +} + +main() { + Expect.equals("A", C1().m()); + Expect.equals("A", C1().m("s")); + Expect.equals("A", C2().m()); + Expect.equals("A", C2().m("s")); + Expect.equals("A", MA().m()); + Expect.equals("A", MA().m("s")); + Expect.equals("A", E.e1.m()); + Expect.equals("A", E.e1.m("s")); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A03_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A03_t01.dart new file mode 100644 index 0000000000..c8840d7192 --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/forwarder_A03_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 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 it is a compile-time error if a class has an +/// interface member `m` and doesn't have a valid concrete implementation of `m` +/// even if it has a non-trivial `noSuchMethod` +/// @author sgrekhov22@gmail.com + +abstract mixin class A { + String m([String s = ""]); +} + +mixin class B { + String m() => "B"; +} + +class C1 extends B implements A { +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + dynamic noSuchMethod(Invocation i) => "C1"; +} + +class C2 with B implements A { +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + dynamic noSuchMethod(Invocation i) => "C2"; +} + +mixin M on B implements A { + dynamic noSuchMethod(Invocation i) => "M"; +} + +class MA = B with M; +// ^^ +// [analyzer] unspecified +// [cfe] unspecified + +enum E with B implements A { +// ^ +// [analyzer] unspecified +// [cfe] unspecified + e1, e2; + dynamic noSuchMethod(Invocation i) => "E"; +} + +main() { + print(C1); + print(C2); + print(MA); + print(E); +} diff --git a/Language/Classes/Instance_Methods/Method_noSuchMethod/override_A01_t01.dart b/Language/Classes/Instance_Methods/Method_noSuchMethod/override_A01_t01.dart new file mode 100644 index 0000000000..6c44693a2b --- /dev/null +++ b/Language/Classes/Instance_Methods/Method_noSuchMethod/override_A01_t01.dart @@ -0,0 +1,90 @@ +// 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 if there is an override of a `noSuchMethod` then +/// those override is called +/// @author sgrekhov22@gmail.com + +import "../../../../Utils/expect.dart"; + +abstract mixin class A { + String m([String s]); + dynamic noSuchMethod(Invocation i) => "A"; +} + +class B { + String m() => "B"; +} + +class C1 extends A implements B { + dynamic noSuchMethod(Invocation i) => "C1"; +} + +class C2 with A implements B { + dynamic noSuchMethod(Invocation i) => "C2"; +} + +mixin M on A implements B {} + +class MA = A with M; + +enum E with A implements B { + e1, e2; + dynamic noSuchMethod(Invocation i) => "E"; +} + +main() { + Expect.equals("C1", C1().m()); + Expect.equals("C1", C1().m("s")); + A a1 = C1(); + Expect.equals("C1", a1.m()); + Expect.equals("C1", a1.m("s")); + B b1 = C1(); + Expect.equals("C1", b1.m()); + + Expect.equals("C2", C2().m()); + Expect.equals("C2", C2().m("s")); + A a2 = C2(); + Expect.equals("C2", a2.m()); + Expect.equals("C2", a2.m("s")); + B b2 = C2(); + Expect.equals("C2", b2.m()); + + Expect.equals("A", MA().m()); + Expect.equals("A", MA().m("s")); + M m = MA(); + Expect.equals("A", m.m()); + Expect.equals("A", m.m("s")); + A a3 = MA(); + Expect.equals("A", a3.m("s")); + + Expect.equals("E", E.e1.m()); + Expect.equals("E", E.e1.m("s")); + A a4 = E.e1; + Expect.equals("E", a4.m()); + Expect.equals("E", a4.m("s")); + B b3 = E.e1; + Expect.equals("E", b3.m()); +}