Skip to content

Commit c37b8b3

Browse files
committed
Test suite.
added omitted expected-warning annotations
1 parent 63ccd04 commit c37b8b3

7 files changed

+323
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// run-pass
2+
3+
#![warn(indirect_structural_match)]
4+
5+
// This test is checking our logic for structural match checking by enumerating
6+
// the different kinds of const expressions. This test is collecting cases where
7+
// we have accepted the const expression as a pattern in the past and wish to
8+
// continue doing so.
9+
//
10+
// Even if a non-structural-match type is part of an expression in a const's
11+
// definition, that does not necessarily disqualify the const from being a match
12+
// pattern: in principle, we just need the types involved in the final value to
13+
// be structurally matchable.
14+
15+
// See also RFC 1445
16+
17+
#![feature(type_ascription)]
18+
19+
#[derive(Copy, Clone, Debug)]
20+
struct NoPartialEq(u32);
21+
22+
#[derive(Copy, Clone, Debug)]
23+
struct NoDerive(u32);
24+
25+
// This impl makes `NoDerive` irreflexive.
26+
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
27+
impl Eq for NoDerive { }
28+
29+
type OND = Option<NoDerive>;
30+
31+
fn main() {
32+
const FIELD1: u32 = NoPartialEq(1).0;
33+
match 1 { FIELD1 => dbg!(FIELD1), _ => panic!("whoops"), };
34+
const FIELD2: u32 = NoDerive(1).0;
35+
match 1 { FIELD2 => dbg!(FIELD2), _ => panic!("whoops"), };
36+
37+
enum CLike { One = 1, #[allow(dead_code)] Two = 2, }
38+
const ONE_CAST: u32 = CLike::One as u32;
39+
match 1 { ONE_CAST => dbg!(ONE_CAST), _ => panic!("whoops"), };
40+
41+
const NO_DERIVE_NONE: OND = None;
42+
const INDIRECT: OND = NO_DERIVE_NONE;
43+
match None { INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
44+
45+
const TUPLE: (OND, OND) = (None, None);
46+
match (None, None) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
47+
48+
const TYPE: OND = None: OND;
49+
match None { TYPE => dbg!(TYPE), _ => panic!("whoops"), };
50+
51+
const ARRAY: [OND; 2] = [None, None];
52+
match [None; 2] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
53+
54+
const REPEAT: [OND; 2] = [None; 2];
55+
match [None, None] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
56+
57+
trait Trait: Sized { const ASSOC: Option<Self>; }
58+
impl Trait for NoDerive { const ASSOC: Option<NoDerive> = None; }
59+
match None { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
60+
61+
const BLOCK: OND = { NoDerive(10); None };
62+
match None { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
63+
64+
const ADDR_OF: &OND = &None;
65+
match &None { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// This test is illustrating the difference between how failing to derive
2+
// `PartialEq` is handled compared to failing to implement it at all.
3+
4+
// See also RFC 1445
5+
6+
#[derive(PartialEq, Eq)]
7+
struct Structural(u32);
8+
9+
struct NoPartialEq(u32);
10+
11+
struct NoDerive(u32);
12+
13+
// This impl makes NoDerive irreflexive.
14+
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
15+
16+
impl Eq for NoDerive { }
17+
18+
const NO_DERIVE_NONE: Option<NoDerive> = None;
19+
const NO_PARTIAL_EQ_NONE: Option<NoPartialEq> = None;
20+
21+
fn main() {
22+
match None {
23+
NO_DERIVE_NONE => println!("NO_DERIVE_NONE"),
24+
_ => panic!("whoops"),
25+
}
26+
27+
match None {
28+
NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
29+
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
30+
_ => panic!("whoops"),
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: to use a constant of type `NoPartialEq` in a pattern, `NoPartialEq` must be annotated with `#[derive(PartialEq, Eq)]`
2+
--> $DIR/reject_non_partial_eq.rs:28:9
3+
|
4+
LL | NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
5+
| ^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#![warn(indirect_structural_match)]
2+
//~^ NOTE lint level defined here
3+
4+
// This test of structural match checking enumerates the different kinds of
5+
// const definitions, collecting cases where the const pattern is rejected.
6+
//
7+
// Note: Even if a non-structural-match type is part of an expression in a
8+
// const's definition, that does not necessarily disqualify the const from being
9+
// a match pattern: in principle, we just need the types involved in the final
10+
// value to be structurally matchable.
11+
12+
// See also RFC 1445
13+
14+
#![feature(type_ascription)]
15+
16+
#[derive(Copy, Clone, Debug)]
17+
struct NoPartialEq;
18+
19+
#[derive(Copy, Clone, Debug)]
20+
struct NoDerive;
21+
22+
// This impl makes `NoDerive` irreflexive.
23+
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
24+
25+
impl Eq for NoDerive { }
26+
27+
type OND = Option<NoDerive>;
28+
29+
struct TrivialEq(OND);
30+
31+
// This impl makes `TrivialEq` trivial.
32+
impl PartialEq for TrivialEq { fn eq(&self, _: &Self) -> bool { true } }
33+
34+
impl Eq for TrivialEq { }
35+
36+
fn main() {
37+
#[derive(PartialEq, Eq, Debug)]
38+
enum Derive<X> { Some(X), None, }
39+
const ENUM: Derive<NoDerive> = Derive::Some(NoDerive);
40+
match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
41+
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
42+
43+
const FIELD: OND = TrivialEq(Some(NoDerive)).0;
44+
match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
45+
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
46+
const NO_DERIVE_SOME: OND = Some(NoDerive);
47+
const INDIRECT: OND = NO_DERIVE_SOME;
48+
match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
49+
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
50+
const TUPLE: (OND, OND) = (None, Some(NoDerive));
51+
match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
52+
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
53+
const TYPE: OND = Some(NoDerive): OND;
54+
match Some(NoDerive) { TYPE => dbg!(TYPE), _ => panic!("whoops"), };
55+
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
56+
const ARRAY: [OND; 2] = [None, Some(NoDerive)];
57+
match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
58+
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
59+
const REPEAT: [OND; 2] = [Some(NoDerive); 2];
60+
match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
61+
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
62+
trait Trait: Sized { const ASSOC: Option<Self>; }
63+
impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
64+
match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
65+
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
66+
const BLOCK: OND = { NoDerive; Some(NoDerive) };
67+
match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
68+
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
69+
const ADDR_OF: &OND = &Some(NoDerive);
70+
match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
71+
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
72+
//~| WARN previously accepted by the compiler but is being phased out
73+
//~| NOTE for more information, see issue #62411
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
2+
--> $DIR/reject_non_structural.rs:40:36
3+
|
4+
LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
5+
| ^^^^
6+
7+
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
8+
--> $DIR/reject_non_structural.rs:44:28
9+
|
10+
LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
11+
| ^^^^^
12+
13+
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
14+
--> $DIR/reject_non_structural.rs:48:27
15+
|
16+
LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
17+
| ^^^^^^^^
18+
19+
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
20+
--> $DIR/reject_non_structural.rs:51:36
21+
|
22+
LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
23+
| ^^^^^
24+
25+
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
26+
--> $DIR/reject_non_structural.rs:54:28
27+
|
28+
LL | match Some(NoDerive) { TYPE => dbg!(TYPE), _ => panic!("whoops"), };
29+
| ^^^^
30+
31+
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
32+
--> $DIR/reject_non_structural.rs:57:36
33+
|
34+
LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
35+
| ^^^^^
36+
37+
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
38+
--> $DIR/reject_non_structural.rs:60:33
39+
|
40+
LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
41+
| ^^^^^^
42+
43+
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
44+
--> $DIR/reject_non_structural.rs:64:28
45+
|
46+
LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
47+
| ^^^^^^^^^^^^^^^
48+
49+
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
50+
--> $DIR/reject_non_structural.rs:67:28
51+
|
52+
LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
53+
| ^^^^^
54+
55+
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
56+
--> $DIR/reject_non_structural.rs:70:29
57+
|
58+
LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
59+
| ^^^^^^^
60+
|
61+
note: lint level defined here
62+
--> $DIR/reject_non_structural.rs:1:9
63+
|
64+
LL | #![warn(indirect_structural_match)]
65+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
66+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
67+
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
68+
69+
error: aborting due to 9 previous errors
70+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// run-pass
2+
3+
// This test is checking our logic for structural match checking by enumerating
4+
// the different kinds of const expressions. This test is collecting cases where
5+
// we have accepted the const expression as a pattern in the past but we want
6+
// to begin warning the user that a future version of Rust may start rejecting
7+
// such const expressions.
8+
9+
// The specific corner cases we are exploring here are instances where the
10+
// const-evaluator computes a value that *does* meet the conditions for
11+
// structural-match, but the const expression itself has abstractions (like
12+
// calls to const functions) that may fit better with a type-based analysis
13+
// rather than a committment to a specific value.
14+
15+
#![warn(indirect_structural_match)]
16+
17+
#[derive(Copy, Clone, Debug)]
18+
struct NoDerive(u32);
19+
20+
// This impl makes `NoDerive` irreflexive.
21+
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
22+
impl Eq for NoDerive { }
23+
24+
fn main() {
25+
const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0];
26+
match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
27+
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
28+
//~| WARN will become a hard error in a future release
29+
30+
const fn build() -> Option<NoDerive> { None }
31+
const CALL: Option<NoDerive> = build();
32+
match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
33+
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
34+
//~| WARN will become a hard error in a future release
35+
36+
impl NoDerive { const fn none() -> Option<NoDerive> { None } }
37+
const METHOD_CALL: Option<NoDerive> = NoDerive::none();
38+
match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
39+
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
40+
//~| WARN will become a hard error in a future release
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
2+
--> $DIR/warn_corner_cases.rs:26:47
3+
|
4+
LL | match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
5+
| ^^^^^
6+
|
7+
note: lint level defined here
8+
--> $DIR/warn_corner_cases.rs:15:9
9+
|
10+
LL | #![warn(indirect_structural_match)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
12+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
13+
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
14+
15+
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
16+
--> $DIR/warn_corner_cases.rs:32:47
17+
|
18+
LL | match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
19+
| ^^^^
20+
|
21+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
22+
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
23+
24+
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
25+
--> $DIR/warn_corner_cases.rs:38:47
26+
|
27+
LL | match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
28+
| ^^^^^^^^^^^
29+
|
30+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
31+
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
32+

0 commit comments

Comments
 (0)