Skip to content

Commit c5fccb9

Browse files
committed
work towards rejecting consts in patterns that do not implement PartialEq
1 parent 19c6502 commit c5fccb9

File tree

8 files changed

+123
-4
lines changed

8 files changed

+123
-4
lines changed

compiler/rustc_lint_defs/src/builtin.rs

+52
Original file line numberDiff line numberDiff line change
@@ -2310,6 +2310,57 @@ declare_lint! {
23102310
};
23112311
}
23122312

2313+
declare_lint! {
2314+
/// The `match_without_partial_eq` lint detects constants that are used in patterns,
2315+
/// whose type does not implement `PartialEq`.
2316+
///
2317+
/// ### Example
2318+
///
2319+
/// ```rust,compile_fail
2320+
/// #![deny(match_without_partial_eq)]
2321+
///
2322+
/// trait EnumSetType {
2323+
/// type Repr;
2324+
/// }
2325+
///
2326+
/// enum Enum8 { }
2327+
/// impl EnumSetType for Enum8 {
2328+
/// type Repr = u8;
2329+
/// }
2330+
///
2331+
/// #[derive(PartialEq, Eq)]
2332+
/// struct EnumSet<T: EnumSetType> {
2333+
/// __enumset_underlying: T::Repr,
2334+
/// }
2335+
///
2336+
/// const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 };
2337+
///
2338+
/// fn main() {
2339+
/// match CONST_SET {
2340+
/// CONST_SET => { /* ok */ }
2341+
/// _ => panic!("match fell through?"),
2342+
/// }
2343+
/// }
2344+
/// ```
2345+
///
2346+
/// {{produces}}
2347+
///
2348+
/// ### Explanation
2349+
///
2350+
/// Previous versions of Rust accepted constants in patterns, even if those constants' types
2351+
/// did not have `PartialEq` implemented. The compiler falls back to comparing the value
2352+
/// field-by-field. In the future we'd like to ensure that pattern matching always
2353+
/// follows `PartialEq` semantics, so that trait bound will become a requirement for
2354+
/// matching on constants.
2355+
pub MATCH_WITHOUT_PARTIAL_EQ,
2356+
Warn,
2357+
"constant in pattern does not implement `PartialEq`",
2358+
@future_incompatible = FutureIncompatibleInfo {
2359+
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
2360+
reference: "issue #X <https://github.com/rust-lang/rust/issues/X>",
2361+
};
2362+
}
2363+
23132364
declare_lint! {
23142365
/// The `ambiguous_associated_items` lint detects ambiguity between
23152366
/// [associated items] and [enum variants].
@@ -3389,6 +3440,7 @@ declare_lint_pass! {
33893440
LOSSY_PROVENANCE_CASTS,
33903441
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
33913442
MACRO_USE_EXTERN_CRATE,
3443+
MATCH_WITHOUT_PARTIAL_EQ,
33923444
META_VARIABLE_MISUSE,
33933445
MISSING_ABI,
33943446
MISSING_FRAGMENT_SPECIFIER,

compiler/rustc_mir_build/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type
229229
.suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
230230
.help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
231231
232+
mir_build_non_partial_eq_match =
233+
to use a constant of type `{$non_peq_ty}` in a pattern, the type must implement `PartialEq`
234+
232235
mir_build_nontrivial_structural_match =
233236
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)]`
234237

compiler/rustc_mir_build/src/errors.rs

+6
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,12 @@ pub struct NontrivialStructuralMatch<'tcx> {
748748
pub non_sm_ty: Ty<'tcx>,
749749
}
750750

751+
#[derive(LintDiagnostic)]
752+
#[diag(mir_build_non_partial_eq_match)]
753+
pub struct NonPartialEqMatch<'tcx> {
754+
pub non_peq_ty: Ty<'tcx>,
755+
}
756+
751757
#[derive(LintDiagnostic)]
752758
#[diag(mir_build_overlapping_range_endpoints)]
753759
#[note]

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use std::cell::Cell;
1616

1717
use super::PatCtxt;
1818
use crate::errors::{
19-
FloatPattern, IndirectStructuralMatch, InvalidPattern, NontrivialStructuralMatch,
20-
PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
19+
FloatPattern, IndirectStructuralMatch, InvalidPattern, NonPartialEqMatch,
20+
NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
2121
};
2222

2323
impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
@@ -235,6 +235,16 @@ impl<'tcx> ConstToPat<'tcx> {
235235
PointerPattern,
236236
);
237237
}
238+
_ if !self.type_may_have_partial_eq_impl(cv.ty()) => {
239+
// Value is structural-match but the type doesn't even implement `PartialEq`...
240+
self.saw_const_match_lint.set(true);
241+
self.tcx().emit_spanned_lint(
242+
lint::builtin::MATCH_WITHOUT_PARTIAL_EQ,
243+
self.id,
244+
self.span,
245+
NonPartialEqMatch { non_peq_ty: cv.ty() },
246+
);
247+
}
238248
_ => {}
239249
}
240250
}

tests/ui/consts/const_in_pattern/issue-65466.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ const C: &[O<B>] = &[O::None];
1515
fn main() {
1616
let x = O::None;
1717
match &[x][..] {
18-
C => (),
18+
C => (), //~WARN: the type must implement `PartialEq`
19+
//~| previously accepted
1920
_ => (),
2021
}
2122
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
warning: to use a constant of type `&[O<B>]` in a pattern, the type must implement `PartialEq`
2+
--> $DIR/issue-65466.rs:18:9
3+
|
4+
LL | C => (),
5+
| ^
6+
|
7+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8+
= note: for more information, see issue #X <https://github.com/rust-lang/rust/issues/X>
9+
= note: `#[warn(match_without_partial_eq)]` on by default
10+
11+
warning: 1 warning emitted
12+
13+
Future incompatibility report: Future breakage diagnostic:
14+
warning: to use a constant of type `&[O<B>]` in a pattern, the type must implement `PartialEq`
15+
--> $DIR/issue-65466.rs:18:9
16+
|
17+
LL | C => (),
18+
| ^
19+
|
20+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
21+
= note: for more information, see issue #X <https://github.com/rust-lang/rust/issues/X>
22+
= note: `#[warn(match_without_partial_eq)]` on by default
23+

tests/ui/match/issue-72896.rs renamed to tests/ui/match/issue-72896-non-partial-eq-const.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 };
1717

1818
fn main() {
1919
match CONST_SET {
20-
CONST_SET => { /* ok */ }
20+
CONST_SET => { /* ok */ } //~WARN: must implement `PartialEq`
21+
//~| previously accepted
2122
_ => panic!("match fell through?"),
2223
}
2324
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
warning: to use a constant of type `EnumSet<Enum8>` in a pattern, the type must implement `PartialEq`
2+
--> $DIR/issue-72896-non-partial-eq-const.rs:20:9
3+
|
4+
LL | CONST_SET => { /* ok */ }
5+
| ^^^^^^^^^
6+
|
7+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8+
= note: for more information, see issue #X <https://github.com/rust-lang/rust/issues/X>
9+
= note: `#[warn(match_without_partial_eq)]` on by default
10+
11+
warning: 1 warning emitted
12+
13+
Future incompatibility report: Future breakage diagnostic:
14+
warning: to use a constant of type `EnumSet<Enum8>` in a pattern, the type must implement `PartialEq`
15+
--> $DIR/issue-72896-non-partial-eq-const.rs:20:9
16+
|
17+
LL | CONST_SET => { /* ok */ }
18+
| ^^^^^^^^^
19+
|
20+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
21+
= note: for more information, see issue #X <https://github.com/rust-lang/rust/issues/X>
22+
= note: `#[warn(match_without_partial_eq)]` on by default
23+

0 commit comments

Comments
 (0)