Skip to content

Commit a8017ae

Browse files
committed
Auto merge of rust-lang#12153 - GuillaumeGomez:non-exhaustive, r=llogiq
Don't emit `derive_partial_eq_without_eq` lint if the type has the `non_exhaustive` attribute Part of rust-lang/rust-clippy#9063. If a type has a field/variant with the `#[non_exhaustive]` attribute or the type itself has it, then do no emit the `derive_partial_eq_without_eq` lint. changelog: Don't emit `derive_partial_eq_without_eq` lint if the type has the `non_exhaustive` attribute
2 parents 99423e8 + fd6e752 commit a8017ae

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

clippy_lints/src/derive.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then};
22
use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy};
3-
use clippy_utils::{is_lint_allowed, match_def_path, paths};
3+
use clippy_utils::{has_non_exhaustive_attr, is_lint_allowed, match_def_path, paths};
44
use rustc_errors::Applicability;
55
use rustc_hir::def_id::DefId;
66
use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
@@ -449,6 +449,7 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
449449
&& let Some(eq_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Eq)
450450
&& let Some(def_id) = trait_ref.trait_def_id()
451451
&& cx.tcx.is_diagnostic_item(sym::PartialEq, def_id)
452+
&& !has_non_exhaustive_attr(cx.tcx, *adt)
452453
&& let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id)
453454
&& !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[])
454455
// If all of our fields implement `Eq`, we can implement `Eq` too

clippy_utils/src/attrs.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_ast::{ast, attr};
22
use rustc_errors::Applicability;
3+
use rustc_middle::ty::{AdtDef, TyCtxt};
34
use rustc_session::Session;
45
use rustc_span::sym;
56
use std::str::FromStr;
@@ -159,3 +160,14 @@ pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool {
159160
.filter_map(ast::Attribute::meta_item_list)
160161
.any(|l| attr::list_contains_name(&l, sym::hidden))
161162
}
163+
164+
pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool {
165+
adt.is_variant_list_non_exhaustive()
166+
|| tcx.has_attr(adt.did(), sym::non_exhaustive)
167+
|| adt.variants().iter().any(|variant_def| {
168+
variant_def.is_field_list_non_exhaustive() || tcx.has_attr(variant_def.def_id, sym::non_exhaustive)
169+
})
170+
|| adt
171+
.all_fields()
172+
.any(|field_def| tcx.has_attr(field_def.did, sym::non_exhaustive))
173+
}

tests/ui/derive_partial_eq_without_eq.fixed

+32
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,36 @@ pub fn _from_mod() -> _hidden::InPubFn {
121121
#[derive(PartialEq)]
122122
struct InternalTy;
123123

124+
// This is a `non_exhaustive` type so should not warn.
125+
#[derive(Debug, PartialEq)]
126+
#[non_exhaustive]
127+
pub struct MissingEqNonExhaustive {
128+
foo: u32,
129+
bar: String,
130+
}
131+
132+
// This is a `non_exhaustive` type so should not warn.
133+
#[derive(Debug, PartialEq)]
134+
pub struct MissingEqNonExhaustive1 {
135+
foo: u32,
136+
#[non_exhaustive]
137+
bar: String,
138+
}
139+
140+
// This is a `non_exhaustive` type so should not warn.
141+
#[derive(Debug, PartialEq)]
142+
#[non_exhaustive]
143+
pub enum MissingEqNonExhaustive2 {
144+
Foo,
145+
Bar,
146+
}
147+
148+
// This is a `non_exhaustive` type so should not warn.
149+
#[derive(Debug, PartialEq)]
150+
pub enum MissingEqNonExhaustive3 {
151+
Foo,
152+
#[non_exhaustive]
153+
Bar,
154+
}
155+
124156
fn main() {}

tests/ui/derive_partial_eq_without_eq.rs

+32
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,36 @@ pub fn _from_mod() -> _hidden::InPubFn {
121121
#[derive(PartialEq)]
122122
struct InternalTy;
123123

124+
// This is a `non_exhaustive` type so should not warn.
125+
#[derive(Debug, PartialEq)]
126+
#[non_exhaustive]
127+
pub struct MissingEqNonExhaustive {
128+
foo: u32,
129+
bar: String,
130+
}
131+
132+
// This is a `non_exhaustive` type so should not warn.
133+
#[derive(Debug, PartialEq)]
134+
pub struct MissingEqNonExhaustive1 {
135+
foo: u32,
136+
#[non_exhaustive]
137+
bar: String,
138+
}
139+
140+
// This is a `non_exhaustive` type so should not warn.
141+
#[derive(Debug, PartialEq)]
142+
#[non_exhaustive]
143+
pub enum MissingEqNonExhaustive2 {
144+
Foo,
145+
Bar,
146+
}
147+
148+
// This is a `non_exhaustive` type so should not warn.
149+
#[derive(Debug, PartialEq)]
150+
pub enum MissingEqNonExhaustive3 {
151+
Foo,
152+
#[non_exhaustive]
153+
Bar,
154+
}
155+
124156
fn main() {}

0 commit comments

Comments
 (0)