--- /dev/null
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapEmbedded(*const NoDerive);
+
+const WRAP_UNSAFE_EMBEDDED: WrapEmbedded = WrapEmbedded(std::ptr::null());
+
+fn main() {
+ match WRAP_UNSAFE_EMBEDDED {
+ WRAP_UNSAFE_EMBEDDED => { println!("WRAP_UNSAFE_EMBEDDED correctly matched itself"); }
+ _ => { panic!("WRAP_UNSAFE_EMBEDDED did not match itself"); }
+ }
+}
--- /dev/null
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<X>(*const X);
+
+const WRAP_UNSAFE_PARAM: WrapParam<NoDerive> = WrapParam(std::ptr::null());
+
+fn main() {
+ match WRAP_UNSAFE_PARAM {
+ WRAP_UNSAFE_PARAM => { println!("WRAP_UNSAFE_PARAM correctly matched itself"); }
+ _ => { panic!("WRAP_UNSAFE_PARAM did not match itself"); }
+ }
+}
--- /dev/null
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapEmbedded(*const NoDerive);
+
+const WRAP_UNSAFE_EMBEDDED: & &WrapEmbedded = & &WrapEmbedded(std::ptr::null());
+
+fn main() {
+ match WRAP_UNSAFE_EMBEDDED {
+ WRAP_UNSAFE_EMBEDDED => { println!("WRAP_UNSAFE_EMBEDDED correctly matched itself"); }
+ _ => { panic!("WRAP_UNSAFE_EMBEDDED did not match itself"); }
+ }
+}
--- /dev/null
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<X>(*const X);
+
+const WRAP_UNSAFE_PARAM: & &WrapParam<NoDerive> = & &WrapParam(std::ptr::null());
+
+fn main() {
+ match WRAP_UNSAFE_PARAM {
+ WRAP_UNSAFE_PARAM => { println!("WRAP_UNSAFE_PARAM correctly matched itself"); }
+ _ => { panic!("WRAP_UNSAFE_PARAM did not match itself"); }
+ }
+}
--- /dev/null
+// rust-lang/rust#62614: we want to allow matching on constants of types that
+// have non-structural-match variants, *if* the constant itself does not use
+// any such variant.
+
+// NOTE: for now, deliberately leaving the lint `indirect_structural_match` set
+// to its default, so that we will not issue a diangostic even if
+// rust-lang/rust#62614 remains an open issue.
+
+// 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;
+const SUM_THREE: Eek = Eek::UnusedByTheConst(Sum(3,0));
+
+const EEK_ZERO: &[Eek] = &[];
+const EEK_ONE: &[Eek] = &[THE_CONST];
+
+pub fn main() {
+ match Eek::UnusedByTheConst(Sum(1,2)) {
+ ref sum if sum == &SUM_THREE => { println!("Hello 0"); }
+ _ => { println!("Gbye"); }
+ }
+
+ match Eek::TheConst {
+ THE_CONST => { println!("Hello 1"); }
+ _ => { println!("Gbye"); }
+ }
+
+
+ match & &Eek::TheConst {
+ & & THE_CONST => { println!("Hello 2"); }
+ _ => { println!("Gbye"); }
+ }
+
+ match & & &[][..] {
+ & & EEK_ZERO => { println!("Hello 3"); }
+ & & EEK_ONE => { println!("Gbye"); }
+ _ => { println!("Gbye"); }
+ }
+
+ match & & &[Eek::TheConst][..] {
+ & & EEK_ZERO => { println!("Gby"); }
+ & & EEK_ONE => { println!("Hello 4"); }
+ _ => { println!("Gbye"); }
+ }
+}
--- /dev/null
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapInline(NoDerive);
+
+const WRAP_DIRECT_INLINE: WrapInline = WrapInline(NoDerive(0));
+
+fn main() {
+ match WRAP_DIRECT_INLINE {
+ WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => { println!("WRAP_DIRECT_INLINE did not match itself"); }
+ }
+}
--- /dev/null
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-direct-struct-embedded.rs:22:9
+ |
+LL | WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<T>(T);
+
+const WRAP_DIRECT_PARAM: WrapParam<NoDerive> = WrapParam(NoDerive(0));
+
+fn main() {
+ match WRAP_DIRECT_PARAM {
+ WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => { println!("WRAP_DIRECT_PARAM did not match itself"); }
+ }
+}
--- /dev/null
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-direct-struct-param.rs:22:9
+ |
+LL | WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapInline<'a>(&'a &'a NoDerive);
+
+const WRAP_DOUBLY_INDIRECT_INLINE: & &WrapInline = & &WrapInline(& & NoDerive(0));
+
+fn main() {
+ match WRAP_DOUBLY_INDIRECT_INLINE {
+ WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { println!("WRAP_DOUBLY_INDIRECT_INLINE correctly did not match itself"); }
+ }
+}
--- /dev/null
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:24:9
+ |
+LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7: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: 1 warning emitted
+
--- /dev/null
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<'a, T>(&'a &'a T);
+
+const WRAP_DOUBLY_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(& & NoDerive(0));
+
+fn main() {
+ match WRAP_DOUBLY_INDIRECT_PARAM {
+ WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { println!("WRAP_DOUBLY_INDIRECT_PARAM correctly did not match itself"); }
+ }
+}
--- /dev/null
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-doubly-indirect-param.rs:24:9
+ |
+LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/cant-hide-behind-doubly-indirect-param.rs:7: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: 1 warning emitted
+
--- /dev/null
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapInline(NoDerive);
+
+const WRAP_INDIRECT_INLINE: & &WrapInline = & &WrapInline(NoDerive(0));
+
+fn main() {
+ match WRAP_INDIRECT_INLINE {
+ WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { println!("WRAP_INDIRECT_INLINE did not match itself"); }
+ }
+}
--- /dev/null
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:24:9
+ |
+LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7: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: 1 warning emitted
+
--- /dev/null
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<T>(T);
+
+const WRAP_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(NoDerive(0));
+
+fn main() {
+ match WRAP_INDIRECT_PARAM {
+ WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { println!("WRAP_INDIRECT_PARAM correctly did not match itself"); }
+ }
+}
--- /dev/null
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/cant-hide-behind-indirect-struct-param.rs:24:9
+ |
+LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/cant-hide-behind-indirect-struct-param.rs:7: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: 1 warning emitted
+
--- /dev/null
+error[E0658]: use of unstable library feature 'structural_match'
+ --> $DIR/feature-gate.rs:29:6
+ |
+LL | impl std::marker::StructuralPartialEq for Foo { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #31434 <https://github.com/rust-lang/rust/issues/31434> for more information
+ = help: add `#![feature(structural_match)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'structural_match'
+ --> $DIR/feature-gate.rs:31:6
+ |
+LL | impl std::marker::StructuralEq for Foo { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #31434 <https://github.com/rust-lang/rust/issues/31434> for more information
+ = help: add `#![feature(structural_match)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// Test that use of structural-match traits is only permitted with a feature gate,
+// and that if a feature gate is supplied, it permits the type to be
+// used in a match.
+
+// revisions: with_gate no_gate
+
+// gate-test-structural_match
+
+#![allow(unused)]
+#![feature(rustc_attrs)]
+#![cfg_attr(with_gate, feature(structural_match))]
+
+
+struct Foo {
+ x: u32
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+#[rustc_error]
+fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error]
+ let y = Foo { x: 1 };
+ match y {
+ FOO => { }
+ _ => { }
+ }
+}
+
+impl std::marker::StructuralPartialEq for Foo { }
+//[no_gate]~^ ERROR use of unstable library feature 'structural_match'
+impl std::marker::StructuralEq for Foo { }
+//[no_gate]~^ ERROR use of unstable library feature 'structural_match'
+
+impl PartialEq<Foo> for Foo {
+ fn eq(&self, other: &Self) -> bool {
+ self.x == other.x
+ }
+}
+impl Eq for Foo { }
--- /dev/null
+error: fatal error triggered by #[rustc_error]
+ --> $DIR/feature-gate.rs:21:1
+ |
+LL | fn main() {
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+
+// This file checks that fn ptrs are considered structurally matchable.
+// See also rust-lang/rust#63479.
+
+fn main() {
+ let mut count = 0;
+
+ // A type which is not structurally matchable:
+ struct NotSM;
+
+ // And one that is:
+ #[derive(PartialEq, Eq)]
+ struct SM;
+
+ fn trivial() {}
+
+ fn sm_to(_: SM) {}
+ fn not_sm_to(_: NotSM) {}
+ fn to_sm() -> SM { SM }
+ fn to_not_sm() -> NotSM { NotSM }
+
+ // To recreate the scenario of interest in #63479, we need to add
+ // a ref-level-of-indirection so that we descend into the type.
+
+ fn r_sm_to(_: &SM) {}
+ fn r_not_sm_to(_: &NotSM) {}
+ fn r_to_r_sm(_: &()) -> &SM { &SM }
+ fn r_to_r_not_sm(_: &()) -> &NotSM { &NotSM }
+
+ #[derive(PartialEq, Eq)]
+ struct Wrap<T>(T);
+
+ // In the code below, we put the match input into a local so that
+ // we can assign it an explicit type that is an fn ptr instead of
+ // a singleton type of the fn itself that the type inference would
+ // otherwise assign.
+
+ // Check that fn() is structural-match
+ const CFN1: Wrap<fn()> = Wrap(trivial);
+ let input: Wrap<fn()> = Wrap(trivial);
+ match Wrap(input) {
+ Wrap(CFN1) => count += 1,
+ Wrap(_) => {}
+ };
+
+ // Check that fn(T) is structural-match when T is too.
+ const CFN2: Wrap<fn(SM)> = Wrap(sm_to);
+ let input: Wrap<fn(SM)> = Wrap(sm_to);
+ match Wrap(input) {
+ Wrap(CFN2) => count += 1,
+ Wrap(_) => {}
+ };
+
+ // Check that fn() -> T is structural-match when T is too.
+ const CFN3: Wrap<fn() -> SM> = Wrap(to_sm);
+ let input: Wrap<fn() -> SM> = Wrap(to_sm);
+ match Wrap(input) {
+ Wrap(CFN3) => count += 1,
+ Wrap(_) => {}
+ };
+
+ // Check that fn(T) is structural-match even if T is not.
+ const CFN4: Wrap<fn(NotSM)> = Wrap(not_sm_to);
+ let input: Wrap<fn(NotSM)> = Wrap(not_sm_to);
+ match Wrap(input) {
+ Wrap(CFN4) => count += 1,
+ Wrap(_) => {}
+ };
+
+ // Check that fn() -> T is structural-match even if T is not.
+ const CFN5: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
+ let input: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
+ match Wrap(input) {
+ Wrap(CFN5) => count += 1,
+ Wrap(_) => {}
+ };
+
+ // Check that fn(&T) is structural-match when T is too.
+ const CFN6: Wrap<fn(&SM)> = Wrap(r_sm_to);
+ let input: Wrap<fn(&SM)> = Wrap(r_sm_to);
+ match Wrap(input) {
+ Wrap(CFN6) => count += 1,
+ Wrap(_) => {}
+ };
+
+ // Check that fn() -> &T is structural-match when T is too.
+ const CFN7: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
+ let input: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
+ match Wrap(input) {
+ Wrap(CFN7) => count += 1,
+ Wrap(_) => {}
+ };
+
+ // Check that fn(T) is structural-match even if T is not.
+ const CFN8: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
+ let input: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
+ match Wrap(input) {
+ Wrap(CFN8) => count += 1,
+ Wrap(_) => {}
+ };
+
+ // Check that fn() -> T is structural-match even if T is not.
+ const CFN9: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
+ let input: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
+ match Wrap(input) {
+ Wrap(CFN9) => count += 1,
+ Wrap(_) => {}
+ };
+
+ // Check that a type which has fn ptrs is structural-match.
+ #[derive(PartialEq, Eq)]
+ struct Foo {
+ alpha: fn(NotSM),
+ beta: fn() -> NotSM,
+ gamma: fn(SM),
+ delta: fn() -> SM,
+ }
+
+ const CFOO: Foo = Foo {
+ alpha: not_sm_to,
+ beta: to_not_sm,
+ gamma: sm_to,
+ delta: to_sm,
+ };
+
+ let input = Foo { alpha: not_sm_to, beta: to_not_sm, gamma: sm_to, delta: to_sm };
+ match input {
+ CFOO => count += 1,
+ Foo { .. } => {}
+ };
+
+ // Final count must be 10 now if all
+ assert_eq!(count, 10);
+}
--- /dev/null
+// Issue 61188 pointed out a case where we hit an ICE during code gen:
+// the compiler assumed that `PartialEq` was always implemented on any
+// use of a `const` item in a pattern context, but the pre-existing
+// structural-match checking was too shallow
+// (see rust-lang/rust#62307), and so we hit cases where we were
+// trying to dispatch to `PartialEq` on types that did not implement
+// that trait.
+
+struct B(i32);
+
+const A: &[B] = &[];
+
+pub fn main() {
+ match &[][..] {
+ A => (),
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => (),
+ }
+}
--- /dev/null
+error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/issue-61188-match-slice-forbidden-without-eq.rs:15:9
+ |
+LL | A => (),
+ | ^
+
+error: aborting due to previous error
+
--- /dev/null
+// RFC 1445 introduced `#[structural_match]`; this attribute must
+// appear on the `struct`/`enum` definition for any `const` used in a
+// pattern.
+//
+// This is our (forever-unstable) way to mark a datatype as having a
+// `PartialEq` implementation that is equivalent to recursion over its
+// substructure. This avoids (at least in the short term) any need to
+// resolve the question of what semantics is used for such matching.
+// (See RFC 1445 for more details and discussion.)
+
+// Issue 62307 pointed out a case where the structural-match checking
+// was too shallow.
+#![warn(indirect_structural_match, nontrivial_structural_match)]
+// run-pass
+
+#[derive(Debug)]
+struct B(i32);
+
+// Overriding `PartialEq` to use this strange notion of "equality" exposes
+// whether `match` is using structural-equality or method-dispatch
+// under the hood, which is the antithesis of rust-lang/rfcs#1445
+impl PartialEq for B {
+ fn eq(&self, other: &B) -> bool { std::cmp::min(self.0, other.0) == 0 }
+}
+
+fn main() {
+ const RR_B0: & & B = & & B(0);
+ const RR_B1: & & B = & & B(1);
+
+ match RR_B0 {
+ RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { }
+ }
+
+ match RR_B1 {
+ RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
+ //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARN this was previously accepted
+ _ => { }
+ }
+}
--- /dev/null
+warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:31:9
+ |
+LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
+ | ^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
+ |
+LL | #![warn(indirect_structural_match, nontrivial_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 `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:38:9
+ |
+LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
+ | ^^^^^
+ |
+ = 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: 2 warnings emitted
+
--- /dev/null
+// run-pass
+
+// The actual regression test from #63479. (Including this because my
+// first draft at fn-ptr-is-structurally-matchable.rs failed to actually
+// cover the case this hit; I've since expanded it accordingly, but the
+// experience left me wary of leaving this regression test out.)
+
+#![warn(pointer_structural_match)]
+
+#[derive(Eq)]
+struct A {
+ a: i64
+}
+
+impl PartialEq for A {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.a.eq(&other.a)
+ }
+}
+
+type Fn = fn(&[A]);
+
+fn my_fn(_args: &[A]) {
+ println!("hello world");
+}
+
+const TEST: Fn = my_fn;
+
+struct B(Fn);
+
+fn main() {
+ let s = B(my_fn);
+ match s {
+ B(TEST) => println!("matched"),
+ //~^ WARN pointers in patterns behave unpredictably
+ //~| WARN this was previously accepted by the compiler but is being phased out
+ _ => panic!("didn't match")
+ };
+}
--- /dev/null
+warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+ --> $DIR/issue-63479-match-fnptr.rs:35:7
+ |
+LL | B(TEST) => println!("matched"),
+ | ^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-63479-match-fnptr.rs:8:9
+ |
+LL | #![warn(pointer_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/70861>
+
+warning: 1 warning emitted
+
--- /dev/null
+// Pre-existing behavior has been to reject patterns with consts
+// denoting non-empty arrays of non-`Eq` types, but *accept* empty
+// arrays of such types.
+//
+// See rust-lang/rust#62336.
+
+// run-pass
+
+#[derive(PartialEq, Debug)]
+struct B(i32);
+
+fn main() {
+ const FOO: [B; 0] = [];
+ match [] {
+ FOO => { }
+ }
+}
--- /dev/null
+use std::f32;
+
+#[derive(PartialEq)]
+struct Foo {
+ x: u32
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+fn main() {
+ let y = Foo { x: 1 };
+ match y {
+ FOO => { }
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => { }
+ }
+
+ let x = 0.0;
+ match x {
+ f32::INFINITY => { }
+ //~^ WARNING floating-point types cannot be used in patterns
+ //~| WARNING will become a hard error in a future release
+ //~| WARNING floating-point types cannot be used in patterns
+ //~| WARNING this was previously accepted by the compiler but is being phased out
+ _ => { }
+ }
+}
--- /dev/null
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/match-forbidden-without-eq.rs:13:9
+ |
+LL | FOO => { }
+ | ^^^
+
+warning: floating-point types cannot be used in patterns
+ --> $DIR/match-forbidden-without-eq.rs:20:9
+ |
+LL | f32::INFINITY => { }
+ | ^^^^^^^^^^^^^
+ |
+ = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+ --> $DIR/match-forbidden-without-eq.rs:20:9
+ |
+LL | f32::INFINITY => { }
+ | ^^^^^^^^^^^^^
+ |
+ = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to previous error; 2 warnings emitted
+
--- /dev/null
+// Issue 62307 pointed out a case where the structural-match checking
+// was too shallow.
+//
+// Here we check similar behavior for non-empty arrays of types that
+// do not derive `Eq`.
+//
+// (Current behavior for empty arrays differs and thus is not tested
+// here; see rust-lang/rust#62336.)
+
+#[derive(PartialEq, Debug)]
+struct B(i32);
+
+fn main() {
+ const FOO: [B; 1] = [B(0)];
+ match [B(1)] {
+ FOO => { }
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ }
+}
--- /dev/null
+error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/match-nonempty-array-forbidden-without-eq.rs:16:9
+ |
+LL | FOO => { }
+ | ^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#[derive(Eq)]
+struct Foo {
+ x: u32
+}
+
+impl PartialEq for Foo {
+ fn eq(&self, _: &Foo) -> bool {
+ false // ha ha sucker!
+ }
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+fn main() {
+ let y = Foo { x: 1 };
+ match y {
+ FOO => { }
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => { }
+ }
+}
--- /dev/null
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/match-requires-both-partialeq-and-eq.rs:17:9
+ |
+LL | FOO => { }
+ | ^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+
+// This file checks that `PhantomData` is considered structurally matchable.
+
+use std::marker::PhantomData;
+
+fn main() {
+ let mut count = 0;
+
+ // A type which is not structurally matchable:
+ struct NotSM;
+
+ // And one that is:
+ #[derive(PartialEq, Eq)]
+ struct SM;
+
+ // Check that SM is structural-match:
+ const CSM: SM = SM;
+ match SM {
+ CSM => count += 1,
+ };
+
+ // Check that PhantomData<T> is structural-match even if T is not.
+ const CPD1: PhantomData<NotSM> = PhantomData;
+ match PhantomData {
+ CPD1 => count += 1,
+ };
+
+ // Check that PhantomData<T> is structural-match when T is.
+ const CPD2: PhantomData<SM> = PhantomData;
+ match PhantomData {
+ CPD2 => count += 1,
+ };
+
+ // Check that a type which has a PhantomData is structural-match.
+ #[derive(PartialEq, Eq, Default)]
+ struct Foo {
+ alpha: PhantomData<NotSM>,
+ beta: PhantomData<SM>,
+ }
+
+ const CFOO: Foo = Foo {
+ alpha: PhantomData,
+ beta: PhantomData,
+ };
+
+ match Foo::default() {
+ CFOO => count += 1,
+ };
+
+ // Final count must be 4 now if all
+ assert_eq!(count, 4);
+}
--- /dev/null
+// compile-flags: -l foo:bar
+// error-pattern: renaming of the library `foo` was specified
+
+#![crate_type = "lib"]
--- /dev/null
+error: renaming of the library `foo` was specified, however this crate contains no `#[link(...)]` attributes referencing this library.
+
+error: aborting due to previous error
+
--- /dev/null
+// compile-flags: -l foo:bar -l foo:baz
+// error-pattern: multiple renamings were specified for library
+
+#![crate_type = "lib"]
+
+#[link(name = "foo")]
+extern "C" {}
--- /dev/null
+error: multiple renamings were specified for library `foo` .
+
+error: aborting due to previous error
+
--- /dev/null
+// compile-flags: -l foo:
+// error-pattern: an empty renaming target was specified for library
+
+#![crate_type = "lib"]
+
+#[link(name = "foo")]
+extern "C" {}
--- /dev/null
+error: an empty renaming target was specified for library `foo`
+
+error: aborting due to previous error
+
+++ /dev/null
-// Test explores how `#[structral_match]` behaves in tandem with
-// `*const` and `*mut` pointers.
-
-// run-pass
-
-#![warn(pointer_structural_match)]
-
-struct NoDerive(i32);
-
-// This impl makes NoDerive irreflexive
-// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
-impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-
-impl Eq for NoDerive { }
-
-#[derive(PartialEq, Eq)]
-struct WrapEmbedded(*const NoDerive);
-
-const WRAP_UNSAFE_EMBEDDED: WrapEmbedded = WrapEmbedded(std::ptr::null());
-
-fn main() {
- match WRAP_UNSAFE_EMBEDDED {
- WRAP_UNSAFE_EMBEDDED => { println!("WRAP_UNSAFE_EMBEDDED correctly matched itself"); }
- _ => { panic!("WRAP_UNSAFE_EMBEDDED did not match itself"); }
- }
-}
+++ /dev/null
-// Test explores how `#[structral_match]` behaves in tandem with
-// `*const` and `*mut` pointers.
-
-// run-pass
-
-#![warn(pointer_structural_match)]
-
-struct NoDerive(i32);
-
-// This impl makes NoDerive irreflexive
-// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
-impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-
-impl Eq for NoDerive { }
-
-#[derive(PartialEq, Eq)]
-struct WrapParam<X>(*const X);
-
-const WRAP_UNSAFE_PARAM: WrapParam<NoDerive> = WrapParam(std::ptr::null());
-
-fn main() {
- match WRAP_UNSAFE_PARAM {
- WRAP_UNSAFE_PARAM => { println!("WRAP_UNSAFE_PARAM correctly matched itself"); }
- _ => { panic!("WRAP_UNSAFE_PARAM did not match itself"); }
- }
-}
+++ /dev/null
-// Test explores how `#[structral_match]` behaves in tandem with
-// `*const` and `*mut` pointers.
-
-// run-pass
-
-#![warn(pointer_structural_match)]
-
-struct NoDerive(i32);
-
-// This impl makes NoDerive irreflexive
-// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
-impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-
-impl Eq for NoDerive { }
-
-#[derive(PartialEq, Eq)]
-struct WrapEmbedded(*const NoDerive);
-
-const WRAP_UNSAFE_EMBEDDED: & &WrapEmbedded = & &WrapEmbedded(std::ptr::null());
-
-fn main() {
- match WRAP_UNSAFE_EMBEDDED {
- WRAP_UNSAFE_EMBEDDED => { println!("WRAP_UNSAFE_EMBEDDED correctly matched itself"); }
- _ => { panic!("WRAP_UNSAFE_EMBEDDED did not match itself"); }
- }
-}
+++ /dev/null
-// Test explores how `#[structral_match]` behaves in tandem with
-// `*const` and `*mut` pointers.
-
-// run-pass
-
-#![warn(pointer_structural_match)]
-
-struct NoDerive(i32);
-
-// This impl makes NoDerive irreflexive
-// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
-impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-
-impl Eq for NoDerive { }
-
-#[derive(PartialEq, Eq)]
-struct WrapParam<X>(*const X);
-
-const WRAP_UNSAFE_PARAM: & &WrapParam<NoDerive> = & &WrapParam(std::ptr::null());
-
-fn main() {
- match WRAP_UNSAFE_PARAM {
- WRAP_UNSAFE_PARAM => { println!("WRAP_UNSAFE_PARAM correctly matched itself"); }
- _ => { panic!("WRAP_UNSAFE_PARAM did not match itself"); }
- }
-}
+++ /dev/null
-// rust-lang/rust#62614: we want to allow matching on constants of types that
-// have non-structural-match variants, *if* the constant itself does not use
-// any such variant.
-
-// NOTE: for now, deliberately leaving the lint `indirect_structural_match` set
-// to its default, so that we will not issue a diangostic even if
-// rust-lang/rust#62614 remains an open issue.
-
-// 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;
-const SUM_THREE: Eek = Eek::UnusedByTheConst(Sum(3,0));
-
-const EEK_ZERO: &[Eek] = &[];
-const EEK_ONE: &[Eek] = &[THE_CONST];
-
-pub fn main() {
- match Eek::UnusedByTheConst(Sum(1,2)) {
- ref sum if sum == &SUM_THREE => { println!("Hello 0"); }
- _ => { println!("Gbye"); }
- }
-
- match Eek::TheConst {
- THE_CONST => { println!("Hello 1"); }
- _ => { println!("Gbye"); }
- }
-
-
- match & &Eek::TheConst {
- & & THE_CONST => { println!("Hello 2"); }
- _ => { println!("Gbye"); }
- }
-
- match & & &[][..] {
- & & EEK_ZERO => { println!("Hello 3"); }
- & & EEK_ONE => { println!("Gbye"); }
- _ => { println!("Gbye"); }
- }
-
- match & & &[Eek::TheConst][..] {
- & & EEK_ZERO => { println!("Gby"); }
- & & EEK_ONE => { println!("Hello 4"); }
- _ => { println!("Gbye"); }
- }
-}
+++ /dev/null
-// This is part of a set of tests exploring the different ways a
-// structural-match ADT might try to hold a
-// non-structural-match in hidden manner that lets matches
-// through that we had intended to reject.
-//
-// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
-
-struct NoDerive(i32);
-
-// This impl makes NoDerive irreflexive.
-impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-
-impl Eq for NoDerive { }
-
-#[derive(PartialEq, Eq)]
-struct WrapInline(NoDerive);
-
-const WRAP_DIRECT_INLINE: WrapInline = WrapInline(NoDerive(0));
-
-fn main() {
- match WRAP_DIRECT_INLINE {
- WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
- //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
- _ => { println!("WRAP_DIRECT_INLINE did not match itself"); }
- }
-}
+++ /dev/null
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/cant-hide-behind-direct-struct-embedded.rs:22:9
- |
-LL | WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
- | ^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-// This is part of a set of tests exploring the different ways a
-// structural-match ADT might try to hold a
-// non-structural-match in hidden manner that lets matches
-// through that we had intended to reject.
-//
-// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
-#![warn(indirect_structural_match)]
-struct NoDerive(i32);
-
-// This impl makes NoDerive irreflexive.
-impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-
-impl Eq for NoDerive { }
-
-#[derive(PartialEq, Eq)]
-struct WrapParam<T>(T);
-
-const WRAP_DIRECT_PARAM: WrapParam<NoDerive> = WrapParam(NoDerive(0));
-
-fn main() {
- match WRAP_DIRECT_PARAM {
- WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
- //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
- _ => { println!("WRAP_DIRECT_PARAM did not match itself"); }
- }
-}
+++ /dev/null
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/cant-hide-behind-direct-struct-param.rs:22:9
- |
-LL | WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
- | ^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-// This is part of a set of tests exploring the different ways a
-// structural-match ADT might try to hold a
-// non-structural-match in hidden manner that lets matches
-// through that we had intended to reject.
-//
-// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
-#![warn(indirect_structural_match)]
-// run-pass
-
-struct NoDerive(i32);
-
-// This impl makes NoDerive irreflexive.
-impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-
-impl Eq for NoDerive { }
-
-#[derive(PartialEq, Eq)]
-struct WrapInline<'a>(&'a &'a NoDerive);
-
-const WRAP_DOUBLY_INDIRECT_INLINE: & &WrapInline = & &WrapInline(& & NoDerive(0));
-
-fn main() {
- match WRAP_DOUBLY_INDIRECT_INLINE {
- WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
- //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
- //~| WARN this was previously accepted
- _ => { println!("WRAP_DOUBLY_INDIRECT_INLINE correctly did not match itself"); }
- }
-}
+++ /dev/null
-warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:24:9
- |
-LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: the lint level is defined here
- --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7: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: 1 warning emitted
-
+++ /dev/null
-// This is part of a set of tests exploring the different ways a
-// structural-match ADT might try to hold a
-// non-structural-match in hidden manner that lets matches
-// through that we had intended to reject.
-//
-// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
-#![warn(indirect_structural_match)]
-// run-pass
-
-struct NoDerive(i32);
-
-// This impl makes NoDerive irreflexive.
-impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-
-impl Eq for NoDerive { }
-
-#[derive(PartialEq, Eq)]
-struct WrapParam<'a, T>(&'a &'a T);
-
-const WRAP_DOUBLY_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(& & NoDerive(0));
-
-fn main() {
- match WRAP_DOUBLY_INDIRECT_PARAM {
- WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
- //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
- //~| WARN this was previously accepted
- _ => { println!("WRAP_DOUBLY_INDIRECT_PARAM correctly did not match itself"); }
- }
-}
+++ /dev/null
-warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/cant-hide-behind-doubly-indirect-param.rs:24:9
- |
-LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: the lint level is defined here
- --> $DIR/cant-hide-behind-doubly-indirect-param.rs:7: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: 1 warning emitted
-
+++ /dev/null
-// This is part of a set of tests exploring the different ways a
-// structural-match ADT might try to hold a
-// non-structural-match in hidden manner that lets matches
-// through that we had intended to reject.
-//
-// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
-#![warn(indirect_structural_match)]
-// run-pass
-
-struct NoDerive(i32);
-
-// This impl makes NoDerive irreflexive.
-impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-
-impl Eq for NoDerive { }
-
-#[derive(PartialEq, Eq)]
-struct WrapInline(NoDerive);
-
-const WRAP_INDIRECT_INLINE: & &WrapInline = & &WrapInline(NoDerive(0));
-
-fn main() {
- match WRAP_INDIRECT_INLINE {
- WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
- //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
- //~| WARN this was previously accepted
- _ => { println!("WRAP_INDIRECT_INLINE did not match itself"); }
- }
-}
+++ /dev/null
-warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:24:9
- |
-LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
- | ^^^^^^^^^^^^^^^^^^^^
- |
-note: the lint level is defined here
- --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7: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: 1 warning emitted
-
+++ /dev/null
-// This is part of a set of tests exploring the different ways a
-// structural-match ADT might try to hold a
-// non-structural-match in hidden manner that lets matches
-// through that we had intended to reject.
-//
-// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
-#![warn(indirect_structural_match)]
-// run-pass
-
-struct NoDerive(i32);
-
-// This impl makes NoDerive irreflexive.
-impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-
-impl Eq for NoDerive { }
-
-#[derive(PartialEq, Eq)]
-struct WrapParam<T>(T);
-
-const WRAP_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(NoDerive(0));
-
-fn main() {
- match WRAP_INDIRECT_PARAM {
- WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
- //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
- //~| WARN this was previously accepted
- _ => { println!("WRAP_INDIRECT_PARAM correctly did not match itself"); }
- }
-}
+++ /dev/null
-warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/cant-hide-behind-indirect-struct-param.rs:24:9
- |
-LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
- | ^^^^^^^^^^^^^^^^^^^
- |
-note: the lint level is defined here
- --> $DIR/cant-hide-behind-indirect-struct-param.rs:7: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: 1 warning emitted
-
+++ /dev/null
-error[E0658]: use of unstable library feature 'structural_match'
- --> $DIR/feature-gate.rs:29:6
- |
-LL | impl std::marker::StructuralPartialEq for Foo { }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #31434 <https://github.com/rust-lang/rust/issues/31434> for more information
- = help: add `#![feature(structural_match)]` to the crate attributes to enable
-
-error[E0658]: use of unstable library feature 'structural_match'
- --> $DIR/feature-gate.rs:31:6
- |
-LL | impl std::marker::StructuralEq for Foo { }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #31434 <https://github.com/rust-lang/rust/issues/31434> for more information
- = help: add `#![feature(structural_match)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
+++ /dev/null
-// Test that use of structural-match traits is only permitted with a feature gate,
-// and that if a feature gate is supplied, it permits the type to be
-// used in a match.
-
-// revisions: with_gate no_gate
-
-// gate-test-structural_match
-
-#![allow(unused)]
-#![feature(rustc_attrs)]
-#![cfg_attr(with_gate, feature(structural_match))]
-
-
-struct Foo {
- x: u32
-}
-
-const FOO: Foo = Foo { x: 0 };
-
-#[rustc_error]
-fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error]
- let y = Foo { x: 1 };
- match y {
- FOO => { }
- _ => { }
- }
-}
-
-impl std::marker::StructuralPartialEq for Foo { }
-//[no_gate]~^ ERROR use of unstable library feature 'structural_match'
-impl std::marker::StructuralEq for Foo { }
-//[no_gate]~^ ERROR use of unstable library feature 'structural_match'
-
-impl PartialEq<Foo> for Foo {
- fn eq(&self, other: &Self) -> bool {
- self.x == other.x
- }
-}
-impl Eq for Foo { }
+++ /dev/null
-error: fatal error triggered by #[rustc_error]
- --> $DIR/feature-gate.rs:21:1
- |
-LL | fn main() {
- | ^^^^^^^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-// run-pass
-
-// This file checks that fn ptrs are considered structurally matchable.
-// See also rust-lang/rust#63479.
-
-fn main() {
- let mut count = 0;
-
- // A type which is not structurally matchable:
- struct NotSM;
-
- // And one that is:
- #[derive(PartialEq, Eq)]
- struct SM;
-
- fn trivial() {}
-
- fn sm_to(_: SM) {}
- fn not_sm_to(_: NotSM) {}
- fn to_sm() -> SM { SM }
- fn to_not_sm() -> NotSM { NotSM }
-
- // To recreate the scenario of interest in #63479, we need to add
- // a ref-level-of-indirection so that we descend into the type.
-
- fn r_sm_to(_: &SM) {}
- fn r_not_sm_to(_: &NotSM) {}
- fn r_to_r_sm(_: &()) -> &SM { &SM }
- fn r_to_r_not_sm(_: &()) -> &NotSM { &NotSM }
-
- #[derive(PartialEq, Eq)]
- struct Wrap<T>(T);
-
- // In the code below, we put the match input into a local so that
- // we can assign it an explicit type that is an fn ptr instead of
- // a singleton type of the fn itself that the type inference would
- // otherwise assign.
-
- // Check that fn() is structural-match
- const CFN1: Wrap<fn()> = Wrap(trivial);
- let input: Wrap<fn()> = Wrap(trivial);
- match Wrap(input) {
- Wrap(CFN1) => count += 1,
- Wrap(_) => {}
- };
-
- // Check that fn(T) is structural-match when T is too.
- const CFN2: Wrap<fn(SM)> = Wrap(sm_to);
- let input: Wrap<fn(SM)> = Wrap(sm_to);
- match Wrap(input) {
- Wrap(CFN2) => count += 1,
- Wrap(_) => {}
- };
-
- // Check that fn() -> T is structural-match when T is too.
- const CFN3: Wrap<fn() -> SM> = Wrap(to_sm);
- let input: Wrap<fn() -> SM> = Wrap(to_sm);
- match Wrap(input) {
- Wrap(CFN3) => count += 1,
- Wrap(_) => {}
- };
-
- // Check that fn(T) is structural-match even if T is not.
- const CFN4: Wrap<fn(NotSM)> = Wrap(not_sm_to);
- let input: Wrap<fn(NotSM)> = Wrap(not_sm_to);
- match Wrap(input) {
- Wrap(CFN4) => count += 1,
- Wrap(_) => {}
- };
-
- // Check that fn() -> T is structural-match even if T is not.
- const CFN5: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
- let input: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
- match Wrap(input) {
- Wrap(CFN5) => count += 1,
- Wrap(_) => {}
- };
-
- // Check that fn(&T) is structural-match when T is too.
- const CFN6: Wrap<fn(&SM)> = Wrap(r_sm_to);
- let input: Wrap<fn(&SM)> = Wrap(r_sm_to);
- match Wrap(input) {
- Wrap(CFN6) => count += 1,
- Wrap(_) => {}
- };
-
- // Check that fn() -> &T is structural-match when T is too.
- const CFN7: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
- let input: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
- match Wrap(input) {
- Wrap(CFN7) => count += 1,
- Wrap(_) => {}
- };
-
- // Check that fn(T) is structural-match even if T is not.
- const CFN8: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
- let input: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
- match Wrap(input) {
- Wrap(CFN8) => count += 1,
- Wrap(_) => {}
- };
-
- // Check that fn() -> T is structural-match even if T is not.
- const CFN9: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
- let input: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
- match Wrap(input) {
- Wrap(CFN9) => count += 1,
- Wrap(_) => {}
- };
-
- // Check that a type which has fn ptrs is structural-match.
- #[derive(PartialEq, Eq)]
- struct Foo {
- alpha: fn(NotSM),
- beta: fn() -> NotSM,
- gamma: fn(SM),
- delta: fn() -> SM,
- }
-
- const CFOO: Foo = Foo {
- alpha: not_sm_to,
- beta: to_not_sm,
- gamma: sm_to,
- delta: to_sm,
- };
-
- let input = Foo { alpha: not_sm_to, beta: to_not_sm, gamma: sm_to, delta: to_sm };
- match input {
- CFOO => count += 1,
- Foo { .. } => {}
- };
-
- // Final count must be 10 now if all
- assert_eq!(count, 10);
-}
+++ /dev/null
-// Issue 61188 pointed out a case where we hit an ICE during code gen:
-// the compiler assumed that `PartialEq` was always implemented on any
-// use of a `const` item in a pattern context, but the pre-existing
-// structural-match checking was too shallow
-// (see rust-lang/rust#62307), and so we hit cases where we were
-// trying to dispatch to `PartialEq` on types that did not implement
-// that trait.
-
-struct B(i32);
-
-const A: &[B] = &[];
-
-pub fn main() {
- match &[][..] {
- A => (),
- //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
- _ => (),
- }
-}
+++ /dev/null
-error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/issue-61188-match-slice-forbidden-without-eq.rs:15:9
- |
-LL | A => (),
- | ^
-
-error: aborting due to previous error
-
+++ /dev/null
-// RFC 1445 introduced `#[structural_match]`; this attribute must
-// appear on the `struct`/`enum` definition for any `const` used in a
-// pattern.
-//
-// This is our (forever-unstable) way to mark a datatype as having a
-// `PartialEq` implementation that is equivalent to recursion over its
-// substructure. This avoids (at least in the short term) any need to
-// resolve the question of what semantics is used for such matching.
-// (See RFC 1445 for more details and discussion.)
-
-// Issue 62307 pointed out a case where the structural-match checking
-// was too shallow.
-#![warn(indirect_structural_match, nontrivial_structural_match)]
-// run-pass
-
-#[derive(Debug)]
-struct B(i32);
-
-// Overriding `PartialEq` to use this strange notion of "equality" exposes
-// whether `match` is using structural-equality or method-dispatch
-// under the hood, which is the antithesis of rust-lang/rfcs#1445
-impl PartialEq for B {
- fn eq(&self, other: &B) -> bool { std::cmp::min(self.0, other.0) == 0 }
-}
-
-fn main() {
- const RR_B0: & & B = & & B(0);
- const RR_B1: & & B = & & B(1);
-
- match RR_B0 {
- RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
- //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
- //~| WARN this was previously accepted
- _ => { }
- }
-
- match RR_B1 {
- RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
- //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
- //~| WARN this was previously accepted
- _ => { }
- }
-}
+++ /dev/null
-warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:31:9
- |
-LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
- | ^^^^^
- |
-note: the lint level is defined here
- --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
- |
-LL | #![warn(indirect_structural_match, nontrivial_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 `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:38:9
- |
-LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
- | ^^^^^
- |
- = 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: 2 warnings emitted
-
+++ /dev/null
-// run-pass
-
-// The actual regression test from #63479. (Including this because my
-// first draft at fn-ptr-is-structurally-matchable.rs failed to actually
-// cover the case this hit; I've since expanded it accordingly, but the
-// experience left me wary of leaving this regression test out.)
-
-#![warn(pointer_structural_match)]
-
-#[derive(Eq)]
-struct A {
- a: i64
-}
-
-impl PartialEq for A {
- #[inline]
- fn eq(&self, other: &Self) -> bool {
- self.a.eq(&other.a)
- }
-}
-
-type Fn = fn(&[A]);
-
-fn my_fn(_args: &[A]) {
- println!("hello world");
-}
-
-const TEST: Fn = my_fn;
-
-struct B(Fn);
-
-fn main() {
- let s = B(my_fn);
- match s {
- B(TEST) => println!("matched"),
- //~^ WARN pointers in patterns behave unpredictably
- //~| WARN this was previously accepted by the compiler but is being phased out
- _ => panic!("didn't match")
- };
-}
+++ /dev/null
-warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
- --> $DIR/issue-63479-match-fnptr.rs:35:7
- |
-LL | B(TEST) => println!("matched"),
- | ^^^^
- |
-note: the lint level is defined here
- --> $DIR/issue-63479-match-fnptr.rs:8:9
- |
-LL | #![warn(pointer_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/70861>
-
-warning: 1 warning emitted
-
+++ /dev/null
-// Pre-existing behavior has been to reject patterns with consts
-// denoting non-empty arrays of non-`Eq` types, but *accept* empty
-// arrays of such types.
-//
-// See rust-lang/rust#62336.
-
-// run-pass
-
-#[derive(PartialEq, Debug)]
-struct B(i32);
-
-fn main() {
- const FOO: [B; 0] = [];
- match [] {
- FOO => { }
- }
-}
+++ /dev/null
-use std::f32;
-
-#[derive(PartialEq)]
-struct Foo {
- x: u32
-}
-
-const FOO: Foo = Foo { x: 0 };
-
-fn main() {
- let y = Foo { x: 1 };
- match y {
- FOO => { }
- //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
- _ => { }
- }
-
- let x = 0.0;
- match x {
- f32::INFINITY => { }
- //~^ WARNING floating-point types cannot be used in patterns
- //~| WARNING will become a hard error in a future release
- //~| WARNING floating-point types cannot be used in patterns
- //~| WARNING this was previously accepted by the compiler but is being phased out
- _ => { }
- }
-}
+++ /dev/null
-error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/match-forbidden-without-eq.rs:13:9
- |
-LL | FOO => { }
- | ^^^
-
-warning: floating-point types cannot be used in patterns
- --> $DIR/match-forbidden-without-eq.rs:20:9
- |
-LL | f32::INFINITY => { }
- | ^^^^^^^^^^^^^
- |
- = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
- --> $DIR/match-forbidden-without-eq.rs:20:9
- |
-LL | f32::INFINITY => { }
- | ^^^^^^^^^^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to previous error; 2 warnings emitted
-
+++ /dev/null
-// Issue 62307 pointed out a case where the structural-match checking
-// was too shallow.
-//
-// Here we check similar behavior for non-empty arrays of types that
-// do not derive `Eq`.
-//
-// (Current behavior for empty arrays differs and thus is not tested
-// here; see rust-lang/rust#62336.)
-
-#[derive(PartialEq, Debug)]
-struct B(i32);
-
-fn main() {
- const FOO: [B; 1] = [B(0)];
- match [B(1)] {
- FOO => { }
- //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
- }
-}
+++ /dev/null
-error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/match-nonempty-array-forbidden-without-eq.rs:16:9
- |
-LL | FOO => { }
- | ^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-#[derive(Eq)]
-struct Foo {
- x: u32
-}
-
-impl PartialEq for Foo {
- fn eq(&self, _: &Foo) -> bool {
- false // ha ha sucker!
- }
-}
-
-const FOO: Foo = Foo { x: 0 };
-
-fn main() {
- let y = Foo { x: 1 };
- match y {
- FOO => { }
- //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
- _ => { }
- }
-}
+++ /dev/null
-error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
- --> $DIR/match-requires-both-partialeq-and-eq.rs:17:9
- |
-LL | FOO => { }
- | ^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-// run-pass
-
-// This file checks that `PhantomData` is considered structurally matchable.
-
-use std::marker::PhantomData;
-
-fn main() {
- let mut count = 0;
-
- // A type which is not structurally matchable:
- struct NotSM;
-
- // And one that is:
- #[derive(PartialEq, Eq)]
- struct SM;
-
- // Check that SM is structural-match:
- const CSM: SM = SM;
- match SM {
- CSM => count += 1,
- };
-
- // Check that PhantomData<T> is structural-match even if T is not.
- const CPD1: PhantomData<NotSM> = PhantomData;
- match PhantomData {
- CPD1 => count += 1,
- };
-
- // Check that PhantomData<T> is structural-match when T is.
- const CPD2: PhantomData<SM> = PhantomData;
- match PhantomData {
- CPD2 => count += 1,
- };
-
- // Check that a type which has a PhantomData is structural-match.
- #[derive(PartialEq, Eq, Default)]
- struct Foo {
- alpha: PhantomData<NotSM>,
- beta: PhantomData<SM>,
- }
-
- const CFOO: Foo = Foo {
- alpha: PhantomData,
- beta: PhantomData,
- };
-
- match Foo::default() {
- CFOO => count += 1,
- };
-
- // Final count must be 4 now if all
- assert_eq!(count, 4);
-}
+++ /dev/null
-// compile-flags: -l foo:bar
-// error-pattern: renaming of the library `foo` was specified
-
-#![crate_type = "lib"]
+++ /dev/null
-error: renaming of the library `foo` was specified, however this crate contains no `#[link(...)]` attributes referencing this library.
-
-error: aborting due to previous error
-
+++ /dev/null
-// compile-flags: -l foo:bar -l foo:baz
-// error-pattern: multiple renamings were specified for library
-
-#![crate_type = "lib"]
-
-#[link(name = "foo")]
-extern "C" {}
+++ /dev/null
-error: multiple renamings were specified for library `foo` .
-
-error: aborting due to previous error
-
+++ /dev/null
-// compile-flags: -l foo:
-// error-pattern: an empty renaming target was specified for library
-
-#![crate_type = "lib"]
-
-#[link(name = "foo")]
-extern "C" {}
+++ /dev/null
-error: an empty renaming target was specified for library `foo`
-
-error: aborting due to previous error
-