Skip to content

Commit 068acbd

Browse files
committed
initial implementation based on code for derive_hash_xor_partial_eq which is showing one error when there should be four
1 parent 0722991 commit 068acbd

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

clippy_lints/src/derive.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
137137
let is_automatically_derived = is_automatically_derived(&*item.attrs);
138138

139139
check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
140+
check_ord_pord(cx, item.span, trait_ref, ty, is_automatically_derived);
140141

141142
if is_automatically_derived {
142143
check_unsafe_derive_deserialize(cx, item, trait_ref, ty);
@@ -201,6 +202,60 @@ fn check_hash_peq<'tcx>(
201202
}
202203
}
203204

205+
/// Implementation of the `DERIVE_ORD_XOR_PARTIAL_ORD` lint.
206+
fn check_ord_pord<'tcx>(
207+
cx: &LateContext<'tcx>,
208+
span: Span,
209+
trait_ref: &TraitRef<'_>,
210+
ty: Ty<'tcx>,
211+
ord_is_automatically_derived: bool,
212+
) {
213+
if_chain! {
214+
if match_path(&trait_ref.path, &paths::ORD);
215+
if let Some(pord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait();
216+
if let Some(def_id) = &trait_ref.trait_def_id();
217+
if !def_id.is_local();
218+
then {
219+
// Look for the PartialOrd implementations for `ty`
220+
cx.tcx.for_each_relevant_impl(pord_trait_def_id, ty, |impl_id| {
221+
let pord_is_automatically_derived = is_automatically_derived(&cx.tcx.get_attrs(impl_id));
222+
223+
if pord_is_automatically_derived == ord_is_automatically_derived {
224+
return;
225+
}
226+
227+
let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");
228+
229+
// Only care about `impl PartialOrd<Foo> for Foo`
230+
// For `impl PartialOrd<B> for A, input_types is [A, B]
231+
if trait_ref.substs.type_at(1) == ty {
232+
let mess = if pord_is_automatically_derived {
233+
"you are implementing `Ord` explicitly but have derived `PartialOrd`"
234+
} else {
235+
"you are deriving `Ord` but have implemented `PartialOrd` explicitly"
236+
};
237+
238+
span_lint_and_then(
239+
cx,
240+
DERIVE_ORD_XOR_PARTIAL_ORD,
241+
span,
242+
mess,
243+
|diag| {
244+
if let Some(local_def_id) = impl_id.as_local() {
245+
let hir_id = cx.tcx.hir().as_local_hir_id(local_def_id);
246+
diag.span_note(
247+
cx.tcx.hir().span(hir_id),
248+
"`PartialOrd` implemented here"
249+
);
250+
}
251+
}
252+
);
253+
}
254+
});
255+
}
256+
}
257+
}
258+
204259
/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
205260
fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &TraitRef<'_>, ty: Ty<'tcx>) {
206261
if match_path(&trait_ref.path, &paths::CLONE_TRAIT) {

0 commit comments

Comments
 (0)