From c15a04211c65e4ef076a58dff92d4d051df8092e Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Thu, 14 Dec 2023 12:35:00 +0200 Subject: [PATCH 1/2] #2420. Add extension types exhaustiveness tests. Variables --- .../exhaustiveness_variable_A01_t01.dart | 45 +++++++++++++++ .../exhaustiveness_variable_A01_t02.dart | 44 +++++++++++++++ .../exhaustiveness_variable_A01_t03.dart | 55 +++++++++++++++++++ .../exhaustiveness_variable_A02_t01.dart | 40 ++++++++++++++ .../exhaustiveness_variable_A02_t02.dart | 46 ++++++++++++++++ .../exhaustiveness_variable_A02_t03.dart | 47 ++++++++++++++++ .../exhaustiveness_sealed_A01_t01.dart | 2 +- 7 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t01.dart create mode 100644 LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t02.dart create mode 100644 LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t03.dart create mode 100644 LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t01.dart create mode 100644 LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t02.dart create mode 100644 LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t03.dart diff --git a/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t01.dart b/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t01.dart new file mode 100644 index 0000000000..fb7da6f17a --- /dev/null +++ b/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t01.dart @@ -0,0 +1,45 @@ +// 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 Switch statements and expressions with a sealed class as a +/// matched type are always exhaustive if the set of cases is exhaustive +/// +/// @description Check that it is no compile-time error if the matched value +/// type of a switch expression is an extension type with a sealed class as a +/// representation type and the set of cases is an exhaustive set of variable +/// patterns +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=inline-class + +import "../../Utils/expect.dart"; + +sealed class A {} + +class B extends A {} + +class C extends B {} + +extension type AET1(A _) {} +extension type AET2(A _) implements A {} +extension type BET1(B _) {} +extension type BET2(B _) implements B {} + +test1_1(AET1 a) => switch (a) { B _ => 'B' }; +test1_2(AET2 a) => switch (a) { B _ => 'B' }; + +test2_1(BET1 b) => switch (b) { B _ => 'B', C _ => 'C' }; +test2_2(BET2 b) => switch (b) { C _ => 'C', B _ => 'B' }; + +main() { + Expect.equals("B", test1_1(AET1(B()))); + Expect.equals("B", test1_1(AET1(C()))); + Expect.equals("B", test1_2(AET2(B()))); + Expect.equals("B", test1_2(AET2(C()))); + + Expect.equals("B", test2_1(BET1(B()))); + Expect.equals("B", test2_1(BET1(C()))); + Expect.equals("B", test2_2(BET2(B()))); + Expect.equals("C", test2_2(BET2(C()))); +} diff --git a/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t02.dart b/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t02.dart new file mode 100644 index 0000000000..2c46d414ba --- /dev/null +++ b/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t02.dart @@ -0,0 +1,44 @@ +// 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 Switch statements and expressions with a sealed class as a +/// matched type are always exhaustive if the set of cases is exhaustive +/// +/// @description Check that it is no compile-time error if the matched value +/// type of a switch expression is a sealed class and the set of cases is an +/// exhaustive set of variable patterns with extension types +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=inline-class + +import "../../Utils/expect.dart"; + +sealed class A {} + +class B extends A {} + +class C extends A {} + +extension type BET1(B _) {} +extension type BET2(B _) implements B {} +extension type CET1(C _) {} +extension type CET2(C _) implements A {} // Let's check implements A, not C + +test1_1(A a) => switch (a) { CET1 _ => 'C', BET1 _ => 'B' }; +test1_2(A a) => switch (a) { BET2 _ => 'B', CET2 _ => 'C' }; + +test2_1(A a) => switch (a) { BET1 _ => 'B', CET1 _ => 'C' }; +test2_2(A a) => switch (a) { CET2 _ => 'C', BET2 _ => 'B' }; + +main() { + Expect.equals("B", test1_1(B())); + Expect.equals("C", test1_1(C())); + Expect.equals("B", test1_2(B())); + Expect.equals("C", test1_2(C())); + + Expect.equals("B", test2_1(B())); + Expect.equals("C", test2_1(C())); + Expect.equals("B", test2_2(B())); + Expect.equals("C", test2_2(C())); +} diff --git a/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t03.dart b/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t03.dart new file mode 100644 index 0000000000..dfb0df2974 --- /dev/null +++ b/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t03.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 Switch statements and expressions with a sealed class as a +/// matched type are always exhaustive if the set of cases is exhaustive +/// +/// @description Check that it is no compile-time error if the matched value +/// type of a switch expression is an extension type with a sealed class as a +/// representation type and the set of cases is an exhaustive set of variable +/// patterns with extension types and classes +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=inline-class + +import "../../Utils/expect.dart"; + +sealed class A {} + +class B extends A {} + +class C extends A {} + +extension type AET1(A _) {} +extension type AET2(A _) implements A {} +extension type BET1(B _) {} +extension type BET2(B _) implements B {} +extension type CET1(C _) {} +extension type CET2(C _) implements C {} + +test1_1(AET1 a) => switch (a) { BET1 _ => 'B', CET1 _ => 'C' }; +test1_2(AET2 a) => switch (a) { BET2 _ => 'B', CET2 _ => 'C' }; + +test2_1(AET1 a) => switch (a) { BET1 _ => 'B', CET1 _ => 'C' }; +test2_2(AET2 a) => switch (a) { CET2 _ => 'C', BET2 _ => 'B' }; + +test3_1(AET1 a) => switch (a) { BET1 _ => 'B', C _ => 'C' }; +test3_2(AET2 a) => switch (a) { CET2 _ => 'C', B _ => 'B' }; + +main() { + Expect.equals("B", test1_1(AET1(B()))); + Expect.equals("C", test1_1(AET1(C()))); + Expect.equals("B", test1_2(AET2(B()))); + Expect.equals("C", test1_2(AET2(C()))); + + Expect.equals("B", test2_1(AET1(B()))); + Expect.equals("C", test2_1(AET1(C()))); + Expect.equals("B", test2_2(AET2(B()))); + Expect.equals("C", test2_2(AET2(C()))); + + Expect.equals("B", test3_1(AET1(B()))); + Expect.equals("C", test3_1(AET1(C()))); + Expect.equals("B", test3_2(AET2(B()))); + Expect.equals("C", test3_2(AET2(C()))); +} diff --git a/LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t01.dart b/LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t01.dart new file mode 100644 index 0000000000..b3de7ebfac --- /dev/null +++ b/LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t01.dart @@ -0,0 +1,40 @@ +// 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 Switch statements and expressions with a sealed class as a +/// matched type are always exhaustive if the set of cases is exhaustive +/// +/// @description Check that it is no compile-time error if the matched value +/// type of a switch expression is an extension type with a sealed class as a +/// representation type and the set of cases is an exhaustive set of variable +/// patterns. Test generic types +/// @author sgrekhov22@gmail.com + +import "../../Utils/expect.dart"; + +sealed class A {} + +class B extends A {} + +class C extends A {} + +extension type AET1(A _) {} +extension type AET2(A _) implements A {} +extension type BET1(B _) {} +extension type BET2(B _) implements B {} + +test1_1(AET1 a) => switch (a) { B _ => 'B'}; +test1_2(AET2 a) => switch (a) { B _ => 'B'}; + +test2_1(AET1 a) => switch (a) { B _ => 'B', C _ => 'C'}; +test2_2(AET2 a) => switch (a) { B _ => 'B', C _ => 'C'}; + +main() { + Expect.equals("B", test1_1(AET1(B()))); + Expect.equals("B", test1_2(AET2(B()))); + Expect.equals("B", test2_1(AET1(B()))); + Expect.equals("B", test2_2(AET2(B()))); + Expect.equals("C", test2_1(AET1(C()))); + Expect.equals("C", test2_2(AET2(C()))); +} diff --git a/LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t02.dart b/LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t02.dart new file mode 100644 index 0000000000..dd84da9944 --- /dev/null +++ b/LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t02.dart @@ -0,0 +1,46 @@ +// 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 Switch statements and expressions with a sealed class as a +/// matched type are always exhaustive if the set of cases is exhaustive +/// +/// @description Check that it is no compile-time error if the matched value +/// type of a switch expression is a sealed class and the set of cases is an +/// exhaustive set of variable patterns with extension types. Test generic types +/// @author sgrekhov22@gmail.com + +import "../../Utils/expect.dart"; + +sealed class A {} + +class B extends A {} + +class C extends A {} + +extension type AET1(A _) {} +extension type AET2(A _) implements A {} +extension type BET1(B _) {} +extension type BET2(B _) implements B {} +extension type CET1(C _) {} +extension type CET2(C _) implements C {} + +test1_1(A a) => switch (a) { BET1 _ => 'B'}; +test1_2(A a) => switch (a) { BET2 _ => 'B'}; + +test2_1(A a) => switch (a) { BET1 _ => 'B', CET1 _ => 'C'}; +test2_2(A a) => switch (a) { BET2 _ => 'B', CET2 _ => 'C'}; + +test3_1(A a) => switch (a) { AET1 _ => 'A'}; +test3_2(A a) => switch (a) { AET2 _ => 'A'}; + +main() { + Expect.equals("B", test1_1(B())); + Expect.equals("B", test1_2(B())); + Expect.equals("B", test2_1(B())); + Expect.equals("B", test2_2(B())); + Expect.equals("C", test2_1(C())); + Expect.equals("C", test2_2(C())); + Expect.equals("A", test3_1(B())); + Expect.equals("A", test3_2(C())); +} diff --git a/LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t03.dart b/LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t03.dart new file mode 100644 index 0000000000..17883525b6 --- /dev/null +++ b/LanguageFeatures/Extension-types/exhaustiveness_variable_A02_t03.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 Switch statements and expressions with a sealed class as a +/// matched type are always exhaustive if the set of cases is exhaustive +/// +/// @description Check that it is no compile-time error if the matched value +/// type of a switch expression is an extension type with a sealed class as a +/// representation type and the set of cases is an exhaustive set of variable +/// patterns with extension types and classes. Test generic types +/// @author sgrekhov22@gmail.com + +import "../../Utils/expect.dart"; + +sealed class A {} + +class B extends A {} + +class C extends A {} + +extension type AET1(A _) {} +extension type AET2(A _) implements A {} +extension type BET1(B _) {} +extension type BET2(B _) implements B {} +extension type CET1(C _) {} +extension type CET2(C _) implements C {} + +test1_1(AET1 a) => switch (a) { BET1 _ => 'B'}; +test1_2(AET2 a) => switch (a) { BET2 _ => 'B'}; + +test2_1(AET1 a) => switch (a) { BET1 _ => 'B', C _ => 'C'}; +test2_2(AET2 a) => switch (a) { B _ => 'B', CET2 _ => 'C'}; + +test3_1(AET1 a) => switch (a) { AET1 _ => 'A'}; +test3_2(AET2 a) => switch (a) { AET2 _ => 'A'}; + +main() { + Expect.equals("B", test1_1(AET1(B()))); + Expect.equals("B", test1_2(AET2(B()))); + Expect.equals("B", test2_1(AET1(B()))); + Expect.equals("B", test2_2(AET2(B()))); + Expect.equals("C", test2_1(AET1(C()))); + Expect.equals("C", test2_2(AET2(C()))); + Expect.equals("A", test3_1(AET1(B()))); + Expect.equals("A", test3_2(AET2(C()))); +} diff --git a/LanguageFeatures/Patterns/Exhaustiveness/exhaustiveness_sealed_A01_t01.dart b/LanguageFeatures/Patterns/Exhaustiveness/exhaustiveness_sealed_A01_t01.dart index f6aa02f1bf..45d74a58d4 100644 --- a/LanguageFeatures/Patterns/Exhaustiveness/exhaustiveness_sealed_A01_t01.dart +++ b/LanguageFeatures/Patterns/Exhaustiveness/exhaustiveness_sealed_A01_t01.dart @@ -20,7 +20,7 @@ class C extends A {} test1(A a) => switch (a) { B _ => 'B'}; -test2(A a) => switch (a) { B _ => 'B', C _ => 'C'}; +test2(A a) => switch (a) { B _ => 'B', C _ => 'C'}; main() { Expect.equals("B", test1(B())); From d898bcfddb0c0e9cd4455e2fe18add8db4640766 Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Mon, 18 Dec 2023 12:55:14 +0200 Subject: [PATCH 2/2] Implement review recommendations --- .../exhaustiveness_variable_A01_t01.dart | 20 +++------- .../exhaustiveness_variable_A01_t04.dart | 37 +++++++++++++++++++ 2 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t04.dart diff --git a/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t01.dart b/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t01.dart index fb7da6f17a..989d30e8d2 100644 --- a/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t01.dart +++ b/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t01.dart @@ -26,20 +26,12 @@ extension type AET2(A _) implements A {} extension type BET1(B _) {} extension type BET2(B _) implements B {} -test1_1(AET1 a) => switch (a) { B _ => 'B' }; -test1_2(AET2 a) => switch (a) { B _ => 'B' }; - -test2_1(BET1 b) => switch (b) { B _ => 'B', C _ => 'C' }; -test2_2(BET2 b) => switch (b) { C _ => 'C', B _ => 'B' }; +test1(AET1 a) => switch (a) { B _ => 'B' }; +test2(AET2 a) => switch (a) { B _ => 'B' }; main() { - Expect.equals("B", test1_1(AET1(B()))); - Expect.equals("B", test1_1(AET1(C()))); - Expect.equals("B", test1_2(AET2(B()))); - Expect.equals("B", test1_2(AET2(C()))); - - Expect.equals("B", test2_1(BET1(B()))); - Expect.equals("B", test2_1(BET1(C()))); - Expect.equals("B", test2_2(BET2(B()))); - Expect.equals("C", test2_2(BET2(C()))); + Expect.equals("B", test1(AET1(B()))); + Expect.equals("B", test1(AET1(C()))); + Expect.equals("B", test2(AET2(B()))); + Expect.equals("B", test2(AET2(C()))); } diff --git a/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t04.dart b/LanguageFeatures/Extension-types/exhaustiveness_variable_A01_t04.dart new file mode 100644 index 0000000000..9a4f994888 --- /dev/null +++ b/LanguageFeatures/Extension-types/exhaustiveness_variable_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 Switch statements and expressions with a some class as a matched +/// type are always exhaustive if the set of cases is exhaustive +/// +/// @description Check that it is no compile-time error if the matched value +/// type of a switch expression is an extension type with some class as a +/// representation type and the set of cases is an exhaustive set of variable +/// patterns +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=inline-class + +import "../../Utils/expect.dart"; + +class A {} + +class B extends A {} + +class C extends B {} + +extension type AET1(A _) {} +extension type AET2(A _) implements A {} +extension type BET1(B _) {} +extension type BET2(B _) implements B {} + +test1(BET1 b) => switch (b) { B _ => 'B' }; +test2(BET2 b) => switch (b) { B _ => 'B' }; + +main() { + Expect.equals("B", test1(BET1(B()))); + Expect.equals("B", test1(BET1(C()))); + Expect.equals("B", test2(BET2(B()))); + Expect.equals("B", test2(BET2(C()))); +}