Skip to content

Commit

Permalink
dart-lang#2420. Add object-pattern exhaustiveness tests (dart-lang#2454)
Browse files Browse the repository at this point in the history
  • Loading branch information
sgrekhov authored Jan 4, 2024
1 parent 575cf4f commit 86b168a
Show file tree
Hide file tree
Showing 6 changed files with 402 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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
///
/// @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 object
/// patterns
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

import "../../Utils/expect.dart";
import "../Patterns/Exhaustiveness/exhaustiveness_lib.dart";

extension type FaceET1<T>(Face<T> _) {}
extension type FaceET2<T>(Face<T> _) implements Face<T> {}

String test1_1(FaceET1 face) => switch (face) {
Jack() => 'Jack',
Queen() => 'Queen',
King(suit: _) => 'King'
};

String test1_2(FaceET2 face) => switch (face) {
Jack() => 'Jack',
Queen() => 'Queen',
King(suit: _) => 'King'
};

String test2_1(FaceET1<int> face) => switch (face) {
Jack<num>() => 'Jack',
Queen<int>() => 'Queen',
King<int>(suit: Suit.club || Suit.diamond || Suit.heart || Suit.spade) =>
'King'
};

String test2_2(FaceET2<int> face) => switch (face) {
Jack<num>() => 'Jack',
Queen<int>() => 'Queen',
King<int>(suit: Suit.club || Suit.diamond || Suit.heart || Suit.spade) =>
'King'
};

String test3_1<T extends num>(FaceET1<T> face) => switch (face) {
Jack<num>() && Jack<T>(oneEyed: _) => 'Jack',
Queen<num>() => 'Queen',
King<T>() => 'King'
};

String test3_2<T extends num>(FaceET2<T> face) => switch (face) {
Jack<num>() && Jack<T>(oneEyed: _) => 'Jack',
Queen<num>() => 'Queen',
King<T>() => 'King'
};

main() {
Expect.equals("King", test1_1(FaceET1(King(Suit.club))));
Expect.equals("King", test1_2(FaceET2(King(Suit.club))));
Expect.equals("King", test2_1(FaceET1(King(Suit.club))));
Expect.equals("King", test2_2(FaceET2(King(Suit.club))));
Expect.equals("King", test3_1<int>(FaceET1(King(Suit.club))));
Expect.equals("King", test3_2<int>(FaceET2(King(Suit.club))));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// 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
///
/// @description Check that it is no compile-time error if the matched value
/// type of a switch statement is an extension type with a sealed class as a
/// representation type and the set of cases is exhaustive
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

import "../../Utils/expect.dart";
import "../Patterns/Exhaustiveness/exhaustiveness_lib.dart";

extension type FaceET1<T>(Face<T> _) {}
extension type FaceET2<T>(Face<T> _) implements Face<T> {}

String test1_1(FaceET1 face) {
switch (face) {
case Jack(): return 'Jack';
case Queen(): return 'Queen';
case King(suit: _): return 'King';
}
}

String test1_2(FaceET2 face) {
switch (face) {
case Jack(): return 'Jack';
case Queen(): return 'Queen';
case King(suit: _): return 'King';
}
}

String test2_1(FaceET1<int> face) {
switch (face) {
case Jack<num>(): return 'Jack';
case Queen<int>(): return 'Queen';
case King<int>(suit: Suit.club || Suit.diamond || Suit.heart || Suit.spade):
return 'King';
}
}

String test2_2(FaceET2<int> face) {
switch (face) {
case Jack<num>(): return 'Jack';
case Queen<int>(): return 'Queen';
case King<int>(suit: Suit.club || Suit.diamond || Suit.heart || Suit.spade):
return 'King';
}
}

String test3_1<T extends num>(FaceET1<T> face) {
switch (face) {
case Jack<num>() && Jack<T>(oneEyed: _): return 'Jack';
case Queen<num>(): return 'Queen';
case King<T>(): return 'King';
}
}

String test3_2<T extends num>(FaceET2<T> face) {
switch (face) {
case Jack<num>() && Jack<T>(oneEyed: _): return 'Jack';
case Queen<num>(): return 'Queen';
case King<T>(): return 'King';
}
}

main() {
Expect.equals("King", test1_1(FaceET1(King(Suit.club))));
Expect.equals("King", test1_2(FaceET2(King(Suit.club))));
Expect.equals("King", test2_1(FaceET1(King(Suit.club))));
Expect.equals("King", test2_2(FaceET2(King(Suit.club))));
Expect.equals("King", test3_1<int>(FaceET1(King(Suit.club))));
Expect.equals("King", test3_2<int>(FaceET2(King(Suit.club))));
}
Original file line number Diff line number Diff line change
@@ -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
///
/// @description Check that it is no compile-time error if the matched value
/// type of a switch expression is a sealed class as and the set of cases is an
/// exhaustive set of object patterns with extension types
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

import "../../Utils/expect.dart";
import "../Patterns/Exhaustiveness/exhaustiveness_lib.dart";

extension type JackET<T>(Jack<T> _) implements Jack<T> {}
extension type QueenET<T>(Queen<T> _) implements Queen<T> {}
extension type KingET<T>(King<T> _) implements King<T> {}

String test1(Face face) => switch (face) {
JackET() || QueenET() => 'Jack or Queen',
KingET(suit: _) => 'King'
};

String test2(Face<int> face) => switch (face) {
JackET<num>() || QueenET<int>() => 'Jack or Queen',
KingET<int>(
suit: Suit.club || Suit.diamond || Suit.heart || Suit.spade
) => 'King'
};

String test3<T extends num>(Face<T> face) => switch (face) {
JackET<num>() && JackET<T>(oneEyed: _) => 'Jack',
QueenET<num>() => 'Queen',
KingET<T>() => 'King'
};

main() {
Expect.equals("Jack or Queen", test1(Jack(Suit.club)));
Expect.equals("Jack or Queen", test2(Jack(Suit.club)));
Expect.equals("King", test3<int>(King(Suit.club)));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// 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
///
/// @description Check that it is no compile-time error if the matched value
/// type of a switch statement is a sealed class as and the set of cases is an
/// exhaustive set of object patterns with extension types
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

import "../../Utils/expect.dart";
import "../Patterns/Exhaustiveness/exhaustiveness_lib.dart";

extension type JackET<T>(Jack<T> _) implements Jack<T> {}
extension type QueenET<T>(Queen<T> _) implements Queen<T> {}
extension type KingET<T>(King<T> _) implements King<T> {}

String test1(Face face) {
switch (face) {
case JackET() || QueenET():
return 'Jack or Queen';
case KingET(suit: _):
return 'King';
}
}

String test2(Face<int> face) {
switch (face) {
case JackET<num>() || QueenET<int>():
return 'Jack or Queen';
case KingET<int>(
suit: Suit.club || Suit.diamond || Suit.heart || Suit.spade
):
return 'King';
}
}

String test3<T extends num>(Face<T> face) {
switch (face) {
case JackET<num>() && JackET<T>(oneEyed: _): return 'Jack';
case QueenET<num>(): return 'Queen';
case KingET<T>(): return 'King';
}
}

main() {
Expect.equals("Jack or Queen", test1(Jack(Suit.club)));
Expect.equals("Jack or Queen", test2(Jack(Suit.club)));
Expect.equals("King", test3<int>(King(Suit.club)));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// 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
///
/// @description Check that it is no compile-time error if the matched value
/// type of a switch is an extension type with a sealed class as a
/// representation type and the set of cases is an exhaustive set of object
/// patterns with extension types
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

import "../../Utils/expect.dart";
import "../Patterns/Exhaustiveness/exhaustiveness_lib.dart";

extension type FaceET1<T>(Face<T> _) {}
extension type FaceET2<T>(Face<T> _) implements Face<T> {}

extension type JackET<T>(Jack<T> _) implements Jack<T> {}
extension type QueenET<T>(Queen<T> _) implements Queen<T> {}
extension type KingET<T>(King<T> _) implements King<T> {}

String test1_1(FaceET1 face) => switch (face) {
JackET() || QueenET() => 'Jack or Queen',
KingET(suit: _) => 'King'
};

String test1_2(FaceET2 face) => switch (face) {
JackET() || QueenET() => 'Jack or Queen',
KingET(suit: _) => 'King'
};

String test2_1(FaceET1<int> face) => switch (face) {
JackET<num>() || QueenET<int>() => 'Jack or Queen',
KingET<int>(
suit: Suit.club || Suit.diamond || Suit.heart || Suit.spade
) => 'King'
};

String test2_2(FaceET2<int> face) => switch (face) {
JackET<num>() || QueenET<int>() => 'Jack or Queen',
KingET<int>(
suit: Suit.club || Suit.diamond || Suit.heart || Suit.spade
) => 'King'
};

String test3_1<T extends num>(FaceET1<T> face) => switch (face) {
JackET<num>() && JackET<T>(oneEyed: _) => 'Jack',
QueenET<num>() => 'Queen',
KingET<T>() => 'King'
};

String test3_2<T extends num>(FaceET2<T> face) => switch (face) {
JackET<num>() && JackET<T>(oneEyed: _) => 'Jack',
QueenET<num>() => 'Queen',
KingET<T>() => 'King'
};

main() {
Expect.equals("Jack or Queen", test1_1(FaceET1(Jack(Suit.club))));
Expect.equals("Jack or Queen", test1_2(FaceET2(Jack(Suit.club))));
Expect.equals("Jack or Queen", test2_1(FaceET1(Jack(Suit.club))));
Expect.equals("Jack or Queen", test2_2(FaceET2(Jack(Suit.club))));
Expect.equals("King", test3_1<int>(FaceET1(King(Suit.club))));
Expect.equals("King", test3_2<int>(FaceET2(King(Suit.club))));
}
Loading

0 comments on commit 86b168a

Please sign in to comment.