diff options
| -rw-r--r-- | compiler/rustc_lint_defs/src/builtin.rs | 52 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/messages.ftl | 3 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/errors.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs | 14 | ||||
| -rw-r--r-- | tests/ui/consts/const_in_pattern/issue-65466.rs | 3 | ||||
| -rw-r--r-- | tests/ui/consts/const_in_pattern/issue-65466.stderr | 23 | ||||
| -rw-r--r-- | tests/ui/match/issue-72896-non-partial-eq-const.rs (renamed from tests/ui/match/issue-72896.rs) | 3 | ||||
| -rw-r--r-- | tests/ui/match/issue-72896-non-partial-eq-const.stderr | 23 |
8 files changed, 123 insertions, 4 deletions
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 1951db49e91..a749c52e2dd 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2311,6 +2311,57 @@ declare_lint! { } declare_lint! { + /// The `match_without_partial_eq` lint detects constants that are used in patterns, + /// whose type does not implement `PartialEq`. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(match_without_partial_eq)] + /// + /// trait EnumSetType { + /// type Repr; + /// } + /// + /// enum Enum8 { } + /// impl EnumSetType for Enum8 { + /// type Repr = u8; + /// } + /// + /// #[derive(PartialEq, Eq)] + /// struct EnumSet<T: EnumSetType> { + /// __enumset_underlying: T::Repr, + /// } + /// + /// const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 }; + /// + /// fn main() { + /// match CONST_SET { + /// CONST_SET => { /* ok */ } + /// _ => panic!("match fell through?"), + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Previous versions of Rust accepted constants in patterns, even if those constants' types + /// did not have `PartialEq` implemented. The compiler falls back to comparing the value + /// field-by-field. In the future we'd like to ensure that pattern matching always + /// follows `PartialEq` semantics, so that trait bound will become a requirement for + /// matching on constants. + pub MATCH_WITHOUT_PARTIAL_EQ, + Warn, + "constant in pattern does not implement `PartialEq`", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #X <https://github.com/rust-lang/rust/issues/X>", + }; +} + +declare_lint! { /// The `ambiguous_associated_items` lint detects ambiguity between /// [associated items] and [enum variants]. /// @@ -3389,6 +3440,7 @@ declare_lint_pass! { LOSSY_PROVENANCE_CASTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, MACRO_USE_EXTERN_CRATE, + MATCH_WITHOUT_PARTIAL_EQ, META_VARIABLE_MISUSE, MISSING_ABI, MISSING_FRAGMENT_SPECIFIER, diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 938f3edd31b..ce021923f64 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -229,6 +229,9 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern +mir_build_non_partial_eq_match = + to use a constant of type `{$non_peq_ty}` in a pattern, the type must implement `PartialEq` + mir_build_nontrivial_structural_match = to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]` diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 3ff3387a781..bee5ac550dd 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -749,6 +749,12 @@ pub struct NontrivialStructuralMatch<'tcx> { } #[derive(LintDiagnostic)] +#[diag(mir_build_non_partial_eq_match)] +pub struct NonPartialEqMatch<'tcx> { + pub non_peq_ty: Ty<'tcx>, +} + +#[derive(LintDiagnostic)] #[diag(mir_build_overlapping_range_endpoints)] #[note] pub struct OverlappingRangeEndpoints<'tcx> { 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 00d9fe72cfc..41f31beff77 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 @@ -16,8 +16,8 @@ use std::cell::Cell; use super::PatCtxt; use crate::errors::{ - FloatPattern, IndirectStructuralMatch, InvalidPattern, NontrivialStructuralMatch, - PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern, + FloatPattern, IndirectStructuralMatch, InvalidPattern, NonPartialEqMatch, + NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern, }; impl<'a, 'tcx> PatCtxt<'a, 'tcx> { @@ -235,6 +235,16 @@ impl<'tcx> ConstToPat<'tcx> { PointerPattern, ); } + _ if !self.type_may_have_partial_eq_impl(cv.ty()) => { + // Value is structural-match but the type doesn't even implement `PartialEq`... + self.saw_const_match_lint.set(true); + self.tcx().emit_spanned_lint( + lint::builtin::MATCH_WITHOUT_PARTIAL_EQ, + self.id, + self.span, + NonPartialEqMatch { non_peq_ty: cv.ty() }, + ); + } _ => {} } } diff --git a/tests/ui/consts/const_in_pattern/issue-65466.rs b/tests/ui/consts/const_in_pattern/issue-65466.rs index 2b421f4c705..d45c32e170a 100644 --- a/tests/ui/consts/const_in_pattern/issue-65466.rs +++ b/tests/ui/consts/const_in_pattern/issue-65466.rs @@ -15,7 +15,8 @@ const C: &[O<B>] = &[O::None]; fn main() { let x = O::None; match &[x][..] { - C => (), + C => (), //~WARN: the type must implement `PartialEq` + //~| previously accepted _ => (), } } diff --git a/tests/ui/consts/const_in_pattern/issue-65466.stderr b/tests/ui/consts/const_in_pattern/issue-65466.stderr new file mode 100644 index 00000000000..89fddbf853d --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-65466.stderr @@ -0,0 +1,23 @@ +warning: to use a constant of type `&[O<B>]` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-65466.rs:18:9 + | +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 #X <https://github.com/rust-lang/rust/issues/X> + = note: `#[warn(match_without_partial_eq)]` on by default + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `&[O<B>]` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-65466.rs:18:9 + | +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 #X <https://github.com/rust-lang/rust/issues/X> + = note: `#[warn(match_without_partial_eq)]` on by default + diff --git a/tests/ui/match/issue-72896.rs b/tests/ui/match/issue-72896-non-partial-eq-const.rs index 3a8b8203731..a3095f0be83 100644 --- a/tests/ui/match/issue-72896.rs +++ b/tests/ui/match/issue-72896-non-partial-eq-const.rs @@ -17,7 +17,8 @@ const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 }; fn main() { match CONST_SET { - CONST_SET => { /* ok */ } + CONST_SET => { /* ok */ } //~WARN: must implement `PartialEq` + //~| previously accepted _ => panic!("match fell through?"), } } diff --git a/tests/ui/match/issue-72896-non-partial-eq-const.stderr b/tests/ui/match/issue-72896-non-partial-eq-const.stderr new file mode 100644 index 00000000000..f32cf439531 --- /dev/null +++ b/tests/ui/match/issue-72896-non-partial-eq-const.stderr @@ -0,0 +1,23 @@ +warning: to use a constant of type `EnumSet<Enum8>` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-72896-non-partial-eq-const.rs:20:9 + | +LL | CONST_SET => { /* ok */ } + | ^^^^^^^^^ + | + = 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 #X <https://github.com/rust-lang/rust/issues/X> + = note: `#[warn(match_without_partial_eq)]` on by default + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `EnumSet<Enum8>` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-72896-non-partial-eq-const.rs:20:9 + | +LL | CONST_SET => { /* ok */ } + | ^^^^^^^^^ + | + = 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 #X <https://github.com/rust-lang/rust/issues/X> + = note: `#[warn(match_without_partial_eq)]` on by default + |
