Skip to content

Commit

Permalink
Add tests from rust-lang#67088 and the issues mentioned in its descri…
Browse files Browse the repository at this point in the history
…ption
  • Loading branch information
ecstatic-morse committed Apr 28, 2020
1 parent 796c0ca commit 66f2d44
Show file tree
Hide file tree
Showing 12 changed files with 468 additions and 16 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"), };
}
24 changes: 24 additions & 0 deletions src/test/ui/consts/const_in_pattern/issue-62614.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// run-pass

struct Sum(u32, u32);

impl PartialEq for Sum {
fn eq(&self, other: &Self) -> bool { self.0 + self.1 == other.0 + other.1 }
}

impl Eq for Sum { }

#[derive(PartialEq, Eq)]
enum Eek {
TheConst,
UnusedByTheConst(Sum)
}

const THE_CONST: Eek = Eek::TheConst;

pub fn main() {
match Eek::UnusedByTheConst(Sum(1,2)) {
THE_CONST => { panic!(); }
_ => {}
}
}
19 changes: 19 additions & 0 deletions src/test/ui/consts/const_in_pattern/issue-65466.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#![deny(indirect_structural_match)]

#[derive(PartialEq, Eq)]
enum O<T> {
Some(*const T), // Can also use PhantomData<T>
None,
}

struct B;

const C: &[O<B>] = &[O::None];

fn main() {
let x = O::None;
match &[x][..] {
C => (),
_ => (),
}
}
15 changes: 15 additions & 0 deletions src/test/ui/consts/const_in_pattern/issue-65466.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0601]: `main` function not found in crate `issue_65466`
--> $DIR/issue-65466.rs:1:1
|
LL | / #![deny(indirect_structural_match)]
LL | |
LL | | #[derive(PartialEq, Eq)]
LL | | enum O<T> {
... |
LL | | }
LL | | }
| |_^ consider adding a `main` function to `$DIR/issue-65466.rs`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0601`.
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

93 changes: 93 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,93 @@
// 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)]
#![warn(indirect_structural_match)]
//~^ NOTE lint level is defined here

#[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)]`
//~| 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)]`
//~| 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)]`
//~| 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)]`
//~| 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)]`
//~| 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)]`
//~| 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)]`
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
//~| 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)]`
//~| 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)]`
//~| 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
}
Loading

0 comments on commit 66f2d44

Please sign in to comment.