diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 9af40acc6d6..f80c60b181e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -43,11 +43,16 @@ struct ConstToPat<'a, 'tcx> { span: Span, param_env: ty::ParamEnv<'tcx>, - // This tracks if we saw some error or lint for a given const value, so that + // This tracks if we emitted some hard error for a given const value, so that // we will not subsequently issue an irrelevant lint for the same const // value. saw_const_match_error: Cell, + // This tracks if we emitted some diagnostic for a given const value, so that + // we will not subsequently issue an irrelevant lint for the same const + // value. + saw_const_match_lint: Cell, + // For backcompat we need to keep allowing non-structurally-eq types behind references. // See also all the `cant-hide-behind` tests. behind_reference: Cell, @@ -75,6 +80,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { param_env: pat_ctxt.param_env, include_lint_checks: pat_ctxt.include_lint_checks, saw_const_match_error: Cell::new(false), + saw_const_match_lint: Cell::new(false), behind_reference: Cell::new(false), } } @@ -165,7 +171,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { if !self.type_has_partial_eq_impl(cv.ty) { // span_fatal avoids ICE from resolution of non-existent method (rare case). self.tcx().sess.span_fatal(self.span, &msg); - } else if mir_structural_match_violation { + } else if mir_structural_match_violation && !self.saw_const_match_lint.get() { self.tcx().struct_span_lint_hir( lint::builtin::INDIRECT_STRUCTURAL_MATCH, self.id, @@ -289,8 +295,11 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { // Backwards compatibility hack because we can't cause hard errors on these // types, so we compare them via `PartialEq::eq` at runtime. ty::Adt(..) if !self.type_marked_structural(cv.ty) && self.behind_reference.get() => { - if self.include_lint_checks && !self.saw_const_match_error.get() { - self.saw_const_match_error.set(true); + if self.include_lint_checks + && !self.saw_const_match_error.get() + && !self.saw_const_match_lint.get() + { + self.saw_const_match_lint.set(true); let msg = format!( "to use a constant of type `{}` in a pattern, \ `{}` must be annotated with `#[derive(PartialEq, Eq)]`", @@ -429,8 +438,11 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { // compilation choices change the runtime behaviour of the match. // See https://github.com/rust-lang/rust/issues/70861 for examples. ty::FnPtr(..) | ty::RawPtr(..) => { - if self.include_lint_checks && !self.saw_const_match_error.get() { - self.saw_const_match_error.set(true); + if self.include_lint_checks + && !self.saw_const_match_error.get() + && !self.saw_const_match_lint.get() + { + self.saw_const_match_lint.set(true); let msg = "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."; @@ -457,12 +469,13 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { if self.include_lint_checks && !self.saw_const_match_error.get() + && !self.saw_const_match_lint.get() && mir_structural_match_violation // FIXME(#73448): Find a way to bring const qualification into parity with // `search_for_structural_match_violation` and then remove this condition. && self.search_for_structural_match_violation(cv.ty).is_some() { - self.saw_const_match_error.set(true); + self.saw_const_match_lint.set(true); let msg = format!( "to use a constant of type `{}` in a pattern, \ the constant's initializer must be trivial or all types \ diff --git a/src/test/ui/consts/match_ice.rs b/src/test/ui/consts/match_ice.rs index db76e230070..73ff15f2122 100644 --- a/src/test/ui/consts/match_ice.rs +++ b/src/test/ui/consts/match_ice.rs @@ -8,10 +8,10 @@ struct T; fn main() { const C: &S = &S; match C { - //~^ non-exhaustive patterns: `&S` not covered C => {} - //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` - //~| WARN was previously accepted by the compiler + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN must be annotated + //~| WARN previously accepted } const K: &T = &T; match K { diff --git a/src/test/ui/consts/match_ice.stderr b/src/test/ui/consts/match_ice.stderr index 6cc79dbca7c..915111b3ce4 100644 --- a/src/test/ui/consts/match_ice.stderr +++ b/src/test/ui/consts/match_ice.stderr @@ -1,5 +1,5 @@ warning: to use a constant of type `&S` in a pattern, the constant's initializer must be trivial or all types in the constant must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/match_ice.rs:12:9 + --> $DIR/match_ice.rs:11:9 | LL | C => {} | ^ @@ -8,18 +8,11 @@ LL | C => {} = 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 #73448 -error[E0004]: non-exhaustive patterns: `&S` not covered - --> $DIR/match_ice.rs:10:11 +error: to use a constant of type `S` in a pattern, `S` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/match_ice.rs:11:9 | -LL | struct S; - | --------- `S` defined here -... -LL | match C { - | ^ pattern `&S` not covered - | - = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms - = note: the matched value is of type `&S` +LL | C => {} + | ^ error: aborting due to previous error; 1 warning emitted -For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc1445/cant-hide-behind-doubly-indirect-embedded.rs b/src/test/ui/rfc1445/cant-hide-behind-doubly-indirect-embedded.rs index f6947819695..fe62774d220 100644 --- a/src/test/ui/rfc1445/cant-hide-behind-doubly-indirect-embedded.rs +++ b/src/test/ui/rfc1445/cant-hide-behind-doubly-indirect-embedded.rs @@ -23,7 +23,7 @@ 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 will become a hard error in a future release + //~| WARN this was previously accepted _ => { println!("WRAP_DOUBLY_INDIRECT_INLINE correctly did not match itself"); } } } diff --git a/src/test/ui/rfc1445/cant-hide-behind-doubly-indirect-param.rs b/src/test/ui/rfc1445/cant-hide-behind-doubly-indirect-param.rs index 1c29d67b655..c3a30674ea3 100644 --- a/src/test/ui/rfc1445/cant-hide-behind-doubly-indirect-param.rs +++ b/src/test/ui/rfc1445/cant-hide-behind-doubly-indirect-param.rs @@ -23,7 +23,7 @@ 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 will become a hard error in a future release + //~| WARN this was previously accepted _ => { println!("WRAP_DOUBLY_INDIRECT_PARAM correctly did not match itself"); } } } diff --git a/src/test/ui/rfc1445/cant-hide-behind-indirect-struct-embedded.rs b/src/test/ui/rfc1445/cant-hide-behind-indirect-struct-embedded.rs index 1a41dbb55c2..4d0e80d5af3 100644 --- a/src/test/ui/rfc1445/cant-hide-behind-indirect-struct-embedded.rs +++ b/src/test/ui/rfc1445/cant-hide-behind-indirect-struct-embedded.rs @@ -23,7 +23,7 @@ fn main() { match WRAP_INDIRECT_INLINE { WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); } //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` - //~| WARN will become a hard error in a future release + //~| WARN this was previously accepted _ => { println!("WRAP_INDIRECT_INLINE did not match itself"); } } } diff --git a/src/test/ui/rfc1445/cant-hide-behind-indirect-struct-param.rs b/src/test/ui/rfc1445/cant-hide-behind-indirect-struct-param.rs index 46032c4b0eb..432f196ec81 100644 --- a/src/test/ui/rfc1445/cant-hide-behind-indirect-struct-param.rs +++ b/src/test/ui/rfc1445/cant-hide-behind-indirect-struct-param.rs @@ -23,7 +23,7 @@ fn main() { match WRAP_INDIRECT_PARAM { WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); } //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` - //~| WARN will become a hard error in a future release + //~| WARN this was previously accepted _ => { println!("WRAP_INDIRECT_PARAM correctly did not match itself"); } } } diff --git a/src/test/ui/rfc1445/issue-62307-match-ref-ref-forbidden-without-eq.rs b/src/test/ui/rfc1445/issue-62307-match-ref-ref-forbidden-without-eq.rs index b5e19611da8..46d8ee3b6be 100644 --- a/src/test/ui/rfc1445/issue-62307-match-ref-ref-forbidden-without-eq.rs +++ b/src/test/ui/rfc1445/issue-62307-match-ref-ref-forbidden-without-eq.rs @@ -30,14 +30,14 @@ fn main() { match RR_B0 { RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); } //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` - //~| WARN will become a hard error in a future release + //~| 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 will become a hard error in a future release + //~| WARN this was previously accepted _ => { } } }