Skip to content

Commit

Permalink
Test suite.
Browse files Browse the repository at this point in the history
added omitted expected-warning annotations
  • Loading branch information
pnkfelix committed Dec 6, 2019
1 parent 63ccd04 commit c37b8b3
Show file tree
Hide file tree
Showing 7 changed files with 323 additions and 0 deletions.
66 changes: 66 additions & 0 deletions src/test/ui/consts/const_in_pattern/accept_structural.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// run-pass

#![warn(indirect_structural_match)]

// This test is checking our logic for structural match checking by enumerating
// the different kinds of const expressions. This test is collecting cases where
// we have accepted the const expression as a pattern in the past and wish to
// continue doing so.
//
// Even if a non-structural-match type is part of an expression in a const's
// definition, that does not necessarily disqualify the const from being a match
// pattern: in principle, we just need the types involved in the final value to
// be structurally matchable.

// See also RFC 1445

#![feature(type_ascription)]

#[derive(Copy, Clone, Debug)]
struct NoPartialEq(u32);

#[derive(Copy, Clone, Debug)]
struct NoDerive(u32);

// This impl makes `NoDerive` irreflexive.
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
impl Eq for NoDerive { }

type OND = Option<NoDerive>;

fn main() {
const FIELD1: u32 = NoPartialEq(1).0;
match 1 { FIELD1 => dbg!(FIELD1), _ => panic!("whoops"), };
const FIELD2: u32 = NoDerive(1).0;
match 1 { FIELD2 => dbg!(FIELD2), _ => panic!("whoops"), };

enum CLike { One = 1, #[allow(dead_code)] Two = 2, }
const ONE_CAST: u32 = CLike::One as u32;
match 1 { ONE_CAST => dbg!(ONE_CAST), _ => panic!("whoops"), };

const NO_DERIVE_NONE: OND = None;
const INDIRECT: OND = NO_DERIVE_NONE;
match None { INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };

const TUPLE: (OND, OND) = (None, None);
match (None, None) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };

const TYPE: OND = None: OND;
match None { TYPE => dbg!(TYPE), _ => panic!("whoops"), };

const ARRAY: [OND; 2] = [None, None];
match [None; 2] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };

const REPEAT: [OND; 2] = [None; 2];
match [None, None] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };

trait Trait: Sized { const ASSOC: Option<Self>; }
impl Trait for NoDerive { const ASSOC: Option<NoDerive> = None; }
match None { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };

const BLOCK: OND = { NoDerive(10); None };
match None { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };

const ADDR_OF: &OND = &None;
match &None { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
}
32 changes: 32 additions & 0 deletions src/test/ui/consts/const_in_pattern/reject_non_partial_eq.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This test is illustrating the difference between how failing to derive
// `PartialEq` is handled compared to failing to implement it at all.

// See also RFC 1445

#[derive(PartialEq, Eq)]
struct Structural(u32);

struct NoPartialEq(u32);

struct NoDerive(u32);

// This impl makes NoDerive irreflexive.
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }

impl Eq for NoDerive { }

const NO_DERIVE_NONE: Option<NoDerive> = None;
const NO_PARTIAL_EQ_NONE: Option<NoPartialEq> = None;

fn main() {
match None {
NO_DERIVE_NONE => println!("NO_DERIVE_NONE"),
_ => panic!("whoops"),
}

match None {
NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
_ => panic!("whoops"),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: to use a constant of type `NoPartialEq` in a pattern, `NoPartialEq` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/reject_non_partial_eq.rs:28:9
|
LL | NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
| ^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

74 changes: 74 additions & 0 deletions src/test/ui/consts/const_in_pattern/reject_non_structural.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#![warn(indirect_structural_match)]
//~^ NOTE lint level defined here

// This test of structural match checking enumerates the different kinds of
// const definitions, collecting cases where the const pattern is rejected.
//
// Note: Even if a non-structural-match type is part of an expression in a
// const's definition, that does not necessarily disqualify the const from being
// a match pattern: in principle, we just need the types involved in the final
// value to be structurally matchable.

// See also RFC 1445

#![feature(type_ascription)]

#[derive(Copy, Clone, Debug)]
struct NoPartialEq;

#[derive(Copy, Clone, Debug)]
struct NoDerive;

// This impl makes `NoDerive` irreflexive.
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }

impl Eq for NoDerive { }

type OND = Option<NoDerive>;

struct TrivialEq(OND);

// This impl makes `TrivialEq` trivial.
impl PartialEq for TrivialEq { fn eq(&self, _: &Self) -> bool { true } }

impl Eq for TrivialEq { }

fn main() {
#[derive(PartialEq, Eq, Debug)]
enum Derive<X> { Some(X), None, }
const ENUM: Derive<NoDerive> = Derive::Some(NoDerive);
match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`

const FIELD: OND = TrivialEq(Some(NoDerive)).0;
match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
const NO_DERIVE_SOME: OND = Some(NoDerive);
const INDIRECT: OND = NO_DERIVE_SOME;
match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
const TUPLE: (OND, OND) = (None, Some(NoDerive));
match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
const TYPE: OND = Some(NoDerive): OND;
match Some(NoDerive) { TYPE => dbg!(TYPE), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
const ARRAY: [OND; 2] = [None, Some(NoDerive)];
match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
const REPEAT: [OND; 2] = [Some(NoDerive); 2];
match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
trait Trait: Sized { const ASSOC: Option<Self>; }
impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
const BLOCK: OND = { NoDerive; Some(NoDerive) };
match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
const ADDR_OF: &OND = &Some(NoDerive);
match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
//~| WARN previously accepted by the compiler but is being phased out
//~| NOTE for more information, see issue #62411
}
70 changes: 70 additions & 0 deletions src/test/ui/consts/const_in_pattern/reject_non_structural.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/reject_non_structural.rs:40:36
|
LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
| ^^^^

error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/reject_non_structural.rs:44:28
|
LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
| ^^^^^

error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/reject_non_structural.rs:48:27
|
LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
| ^^^^^^^^

error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/reject_non_structural.rs:51:36
|
LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
| ^^^^^

error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/reject_non_structural.rs:54:28
|
LL | match Some(NoDerive) { TYPE => dbg!(TYPE), _ => panic!("whoops"), };
| ^^^^

error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/reject_non_structural.rs:57:36
|
LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
| ^^^^^

error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/reject_non_structural.rs:60:33
|
LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
| ^^^^^^

error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/reject_non_structural.rs:64:28
|
LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
| ^^^^^^^^^^^^^^^

error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/reject_non_structural.rs:67:28
|
LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
| ^^^^^

warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/reject_non_structural.rs:70:29
|
LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
| ^^^^^^^
|
note: lint level defined here
--> $DIR/reject_non_structural.rs:1:9
|
LL | #![warn(indirect_structural_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>

error: aborting due to 9 previous errors

41 changes: 41 additions & 0 deletions src/test/ui/consts/const_in_pattern/warn_corner_cases.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// run-pass

// This test is checking our logic for structural match checking by enumerating
// the different kinds of const expressions. This test is collecting cases where
// we have accepted the const expression as a pattern in the past but we want
// to begin warning the user that a future version of Rust may start rejecting
// such const expressions.

// The specific corner cases we are exploring here are instances where the
// const-evaluator computes a value that *does* meet the conditions for
// structural-match, but the const expression itself has abstractions (like
// calls to const functions) that may fit better with a type-based analysis
// rather than a committment to a specific value.

#![warn(indirect_structural_match)]

#[derive(Copy, Clone, Debug)]
struct NoDerive(u32);

// This impl makes `NoDerive` irreflexive.
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
impl Eq for NoDerive { }

fn main() {
const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0];
match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
//~| WARN will become a hard error in a future release

const fn build() -> Option<NoDerive> { None }
const CALL: Option<NoDerive> = build();
match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
//~| WARN will become a hard error in a future release

impl NoDerive { const fn none() -> Option<NoDerive> { None } }
const METHOD_CALL: Option<NoDerive> = NoDerive::none();
match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
//~| WARN will become a hard error in a future release
}
32 changes: 32 additions & 0 deletions src/test/ui/consts/const_in_pattern/warn_corner_cases.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/warn_corner_cases.rs:26:47
|
LL | match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
| ^^^^^
|
note: lint level defined here
--> $DIR/warn_corner_cases.rs:15:9
|
LL | #![warn(indirect_structural_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>

warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/warn_corner_cases.rs:32:47
|
LL | match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
| ^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>

warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/warn_corner_cases.rs:38:47
|
LL | match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>

0 comments on commit c37b8b3

Please sign in to comment.