Skip to content

Commit

Permalink
Rollup merge of #120805 - RalfJung:const-pat-partial-eq, r=oli-obk
Browse files Browse the repository at this point in the history
make non-PartialEq-typed consts as patterns a hard error

This lint was introduced in #115893, for Rust 1.74, so we just had the third stable release where this is shown as a future-compat lint (which is shown for dependencies). Not a single comment or backreference showed up in the tracking issue, #116122. So this seems fairly safe to turn into a hard error.

Of course we should do a crater run first.

This is part of #120362.
Closes #116122.
  • Loading branch information
matthiaskrgr authored Feb 25, 2024
2 parents e13f454 + 5b7786c commit c99902e
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 112 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,11 @@ fn register_builtins(store: &mut LintStore) {
"no longer needed, see #93367 \
<https://github.com/rust-lang/rust/issues/93367> for more information",
);
store.register_removed(
"const_patterns_without_partial_eq",
"converted into hard error, see RFC #3535 \
<https://rust-lang.github.io/rfcs/3535-constants-in-patterns.html> for more information",
);
}

fn register_internals(store: &mut LintStore) {
Expand Down
52 changes: 0 additions & 52 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ declare_lint_pass! {
CONFLICTING_REPR_HINTS,
CONST_EVALUATABLE_UNCHECKED,
CONST_ITEM_MUTATION,
CONST_PATTERNS_WITHOUT_PARTIAL_EQ,
DEAD_CODE,
DEPRECATED,
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
Expand Down Expand Up @@ -2342,57 +2341,6 @@ declare_lint! {
};
}

declare_lint! {
/// The `const_patterns_without_partial_eq` lint detects constants that are used in patterns,
/// whose type does not implement `PartialEq`.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(const_patterns_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 CONST_PATTERNS_WITHOUT_PARTIAL_EQ,
Warn,
"constant in pattern does not implement `PartialEq`",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reference: "issue #116122 <https://github.com/rust-lang/rust/issues/116122>",
};
}

declare_lint! {
/// The `ambiguous_associated_items` lint detects ambiguity between
/// [associated items] and [enum variants].
Expand Down
14 changes: 8 additions & 6 deletions compiler/rustc_mir_build/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,14 @@ pub struct TypeNotStructural<'tcx> {
pub non_sm_ty: Ty<'tcx>,
}

#[derive(Diagnostic)]
#[diag(mir_build_non_partial_eq_match)]
pub struct TypeNotPartialEq<'tcx> {
#[primary_span]
pub span: Span,
pub non_peq_ty: Ty<'tcx>,
}

#[derive(Diagnostic)]
#[diag(mir_build_invalid_pattern)]
pub struct InvalidPattern<'tcx> {
Expand Down Expand Up @@ -822,12 +830,6 @@ pub struct NontrivialStructuralMatch<'tcx> {
pub non_sm_ty: Ty<'tcx>,
}

#[derive(LintDiagnostic)]
#[diag(mir_build_non_partial_eq_match)]
pub struct NonPartialEqMatch<'tcx> {
pub non_peq_ty: Ty<'tcx>,
}

#[derive(Diagnostic)]
#[diag(mir_build_pattern_not_covered, code = E0005)]
pub(crate) struct PatternNotCovered<'s, 'tcx> {
Expand Down
15 changes: 6 additions & 9 deletions compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::cell::Cell;

use super::PatCtxt;
use crate::errors::{
IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch, PointerPattern,
IndirectStructuralMatch, InvalidPattern, NaNPattern, PointerPattern, TypeNotPartialEq,
TypeNotStructural, UnionPattern, UnsizedPattern,
};

Expand Down Expand Up @@ -208,15 +208,12 @@ impl<'tcx> ConstToPat<'tcx> {
);
}

// Always check for `PartialEq`, even if we emitted other lints. (But not if there were
// any errors.) This ensures it shows up in cargo's future-compat reports as well.
// Always check for `PartialEq` if we had no other errors yet.
if !self.type_has_partial_eq_impl(cv.ty()) {
self.tcx().emit_node_span_lint(
lint::builtin::CONST_PATTERNS_WITHOUT_PARTIAL_EQ,
self.id,
self.span,
NonPartialEqMatch { non_peq_ty: cv.ty() },
);
let err = TypeNotPartialEq { span: self.span, non_peq_ty: cv.ty() };
let e = self.tcx().dcx().emit_err(err);
let kind = PatKind::Error(e);
return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
}
}

Expand Down
7 changes: 1 addition & 6 deletions tests/ui/consts/const_in_pattern/issue-65466.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
#![deny(indirect_structural_match)]

//@ check-pass

#[derive(PartialEq, Eq)]
enum O<T> {
Some(*const T), // Can also use PhantomData<T>
Expand All @@ -15,8 +11,7 @@ const C: &[O<B>] = &[O::None];
fn main() {
let x = O::None;
match &[x][..] {
C => (), //~WARN: the type must implement `PartialEq`
//~| previously accepted
C => (), //~ERROR: the type must implement `PartialEq`
_ => (),
}
}
21 changes: 3 additions & 18 deletions tests/ui/consts/const_in_pattern/issue-65466.stderr
Original file line number Diff line number Diff line change
@@ -1,23 +1,8 @@
warning: to use a constant of type `&[O<B>]` in a pattern, the type must implement `PartialEq`
--> $DIR/issue-65466.rs:18:9
error: to use a constant of type `&[O<B>]` in a pattern, the type must implement `PartialEq`
--> $DIR/issue-65466.rs:14: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 #116122 <https://github.com/rust-lang/rust/issues/116122>
= note: `#[warn(const_patterns_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 #116122 <https://github.com/rust-lang/rust/issues/116122>
= note: `#[warn(const_patterns_without_partial_eq)]` on by default
error: aborting due to 1 previous error

4 changes: 1 addition & 3 deletions tests/ui/match/issue-72896-non-partial-eq-const.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//@ run-pass
trait EnumSetType {
type Repr;
}
Expand All @@ -17,8 +16,7 @@ const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 };

fn main() {
match CONST_SET {
CONST_SET => { /* ok */ } //~WARN: must implement `PartialEq`
//~| previously accepted
CONST_SET => { /* ok */ } //~ERROR: must implement `PartialEq`
_ => panic!("match fell through?"),
}
}
21 changes: 3 additions & 18 deletions tests/ui/match/issue-72896-non-partial-eq-const.stderr
Original file line number Diff line number Diff line change
@@ -1,23 +1,8 @@
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
error: to use a constant of type `EnumSet<Enum8>` in a pattern, the type must implement `PartialEq`
--> $DIR/issue-72896-non-partial-eq-const.rs:19: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 #116122 <https://github.com/rust-lang/rust/issues/116122>
= note: `#[warn(const_patterns_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 #116122 <https://github.com/rust-lang/rust/issues/116122>
= note: `#[warn(const_patterns_without_partial_eq)]` on by default
error: aborting due to 1 previous error

0 comments on commit c99902e

Please sign in to comment.