Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make non-PartialEq-typed consts as patterns a hard error #120805

Merged
merged 1 commit into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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:/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:/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:/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:/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:/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:/rust-lang/rust/issues/116122>
= note: `#[warn(const_patterns_without_partial_eq)]` on by default
error: aborting due to 1 previous error

Loading