Skip to content

Commit 844afbf

Browse files
committed
use other instead of self
1 parent 004e89d commit 844afbf

14 files changed

+202
-283
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4834,6 +4834,7 @@ Released 2018-09-13
48344834
[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
48354835
[`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor
48364836
[`incorrect_clone_impl_on_copy_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_clone_impl_on_copy_type
4837+
[`incorrect_partial_ord_impl_on_ord_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_partial_ord_impl_on_ord_type
48374838
[`index_refutable_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice
48384839
[`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing
48394840
[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask
@@ -5020,7 +5021,6 @@ Released 2018-09-13
50205021
[`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref
50215022
[`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take
50225023
[`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals
5023-
[`needless_partial_ord_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_partial_ord_impl
50245024
[`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value
50255025
[`needless_pub_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pub_self
50265026
[`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
207207
crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO,
208208
crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO,
209209
crate::incorrect_impls::INCORRECT_CLONE_IMPL_ON_COPY_TYPE_INFO,
210+
crate::incorrect_impls::INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE_INFO,
210211
crate::index_refutable_slice::INDEX_REFUTABLE_SLICE_INFO,
211212
crate::indexing_slicing::INDEXING_SLICING_INFO,
212213
crate::indexing_slicing::OUT_OF_BOUNDS_INDEXING_INFO,
@@ -469,7 +470,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
469470
crate::needless_else::NEEDLESS_ELSE_INFO,
470471
crate::needless_for_each::NEEDLESS_FOR_EACH_INFO,
471472
crate::needless_if::NEEDLESS_IF_INFO,
472-
crate::needless_impls::NEEDLESS_PARTIAL_ORD_IMPL_INFO,
473473
crate::needless_late_init::NEEDLESS_LATE_INIT_INFO,
474474
crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO,
475475
crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO,

clippy_lints/src/incorrect_impls.rs

Lines changed: 124 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
use clippy_utils::{diagnostics::span_lint_and_sugg, get_parent_node, last_path_segment, ty::implements_trait};
1+
use clippy_utils::{
2+
diagnostics::{span_lint_and_sugg, span_lint_and_then},
3+
get_parent_node, is_res_lang_ctor, last_path_segment, path_res,
4+
ty::implements_trait,
5+
};
26
use rustc_errors::Applicability;
7+
use rustc_hir::{def::Res, Expr, ExprKind, ImplItem, ImplItemKind, ItemKind, LangItem, Node, PatKind, UnOp};
38
use rustc_hir::{ExprKind, ImplItem, ImplItemKind, Node, UnOp};
49
use rustc_lint::{LateContext, LateLintPass};
510
use rustc_middle::ty::EarlyBinder;
611
use rustc_session::{declare_lint_pass, declare_tool_lint};
712
use rustc_span::{sym, symbol};
13+
use std::borrow::Cow;
814

915
declare_clippy_lint! {
1016
/// ### What it does
@@ -45,10 +51,59 @@ declare_clippy_lint! {
4551
correctness,
4652
"manual implementation of `Clone` on a `Copy` type"
4753
}
48-
declare_lint_pass!(IncorrectImpls => [INCORRECT_CLONE_IMPL_ON_COPY_TYPE]);
54+
declare_clippy_lint! {
55+
/// ### What it does
56+
/// Checks for manual implementations of both `PartialOrd` and `Ord` when only `Ord` is
57+
/// necessary.
58+
///
59+
/// ### Why is this bad?
60+
/// If both `PartialOrd` and `Ord` are implemented, they must agree. This is commonly done by
61+
/// wrapping the result of `cmp` in `Some` for `partial_cmp`. Not doing this may silently
62+
/// introduce an error upon refactoring.
63+
///
64+
/// ### Example
65+
/// ```rust,ignore
66+
/// #[derive(Eq, PartialEq)]
67+
/// struct A(u32);
68+
///
69+
/// impl Ord for A {
70+
/// fn cmp(&self, other: &Self) -> Ordering {
71+
/// todo!();
72+
/// }
73+
/// }
74+
///
75+
/// impl PartialOrd for A {
76+
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
77+
/// todo!();
78+
/// }
79+
/// }
80+
/// ```
81+
/// Use instead:
82+
/// ```rust,ignore
83+
/// #[derive(Eq, PartialEq)]
84+
/// struct A(u32);
85+
///
86+
/// impl Ord for A {
87+
/// fn cmp(&self, other: &Self) -> Ordering {
88+
/// todo!();
89+
/// }
90+
/// }
91+
///
92+
/// impl PartialOrd for A {
93+
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
94+
/// Some(self.cmp(other))
95+
/// }
96+
/// }
97+
/// ```
98+
#[clippy::version = "1.72.0"]
99+
pub INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE,
100+
correctness,
101+
"manual implementation of `PartialOrd` when `Ord` is already implemented"
102+
}
103+
declare_lint_pass!(IncorrectImpls => [INCORRECT_CLONE_IMPL_ON_COPY_TYPE, INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE]);
49104

50105
impl LateLintPass<'_> for IncorrectImpls {
51-
#[expect(clippy::needless_return)]
106+
#[expect(clippy::too_many_lines)]
52107
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
53108
let node = get_parent_node(cx.tcx, impl_item.hir_id());
54109
let Some(Node::Item(item)) = node else {
@@ -68,10 +123,7 @@ impl LateLintPass<'_> for IncorrectImpls {
68123
let ExprKind::Block(block, ..) = body.value.kind else {
69124
return;
70125
};
71-
// Above is duplicated from the `duplicate_manual_partial_ord_impl` branch.
72-
// Remove it while solving conflicts once that PR is merged.
73126

74-
// Actual implementation; remove this comment once aforementioned PR is merged
75127
if cx.tcx.is_diagnostic_item(sym::Clone, trait_impl_def_id)
76128
&& let Some(copy_def_id) = cx.tcx.get_diagnostic_item(sym::Copy)
77129
&& implements_trait(
@@ -116,5 +168,71 @@ impl LateLintPass<'_> for IncorrectImpls {
116168
return;
117169
}
118170
}
171+
172+
if cx.tcx.is_diagnostic_item(sym::PartialOrd, trait_impl_def_id)
173+
&& impl_item.ident.name == sym::partial_cmp
174+
&& let Some(ord_def_id) = cx
175+
.tcx
176+
.diagnostic_items(trait_impl.def_id.krate)
177+
.name_to_id
178+
.get(&sym::Ord)
179+
&& implements_trait(
180+
cx,
181+
hir_ty_to_ty(cx.tcx, imp.self_ty),
182+
*ord_def_id,
183+
trait_impl.substs,
184+
)
185+
{
186+
if block.stmts.is_empty()
187+
&& let Some(expr) = block.expr
188+
&& let ExprKind::Call(
189+
Expr {
190+
kind: ExprKind::Path(some_path),
191+
hir_id: some_hir_id,
192+
..
193+
},
194+
[cmp_expr],
195+
) = expr.kind
196+
&& is_res_lang_ctor(cx, cx.qpath_res(some_path, *some_hir_id), LangItem::OptionSome)
197+
&& let ExprKind::MethodCall(cmp_path, _, [other_expr], ..) = cmp_expr.kind
198+
&& cmp_path.ident.name == sym::cmp
199+
&& let Res::Local(..) = path_res(cx, other_expr)
200+
{} else {
201+
// If lhs and rhs are not the same type, bail. This makes creating a valid
202+
// suggestion tons more complex.
203+
if let Some(lhs) = trait_impl.substs.get(0)
204+
&& let Some(rhs) = trait_impl.substs.get(1)
205+
&& lhs != rhs
206+
{
207+
return;
208+
}
209+
210+
span_lint_and_then(
211+
cx,
212+
INCORRECT_PARTIAL_ORD_IMPL_ON_ORD_TYPE,
213+
item.span,
214+
"incorrect implementation of `partial_cmp` on an `Ord` type",
215+
|diag| {
216+
let (help, app) = if let Some(other) = body.params.get(1)
217+
&& let PatKind::Binding(_, _, other_ident, ..) = other.pat.kind
218+
{
219+
(
220+
Cow::Owned(format!("{{ Some(self.cmp({})) }}", other_ident.name)),
221+
Applicability::Unspecified,
222+
)
223+
} else {
224+
(Cow::Borrowed("{ Some(self.cmp(...)) }"), Applicability::HasPlaceholders)
225+
};
226+
227+
diag.span_suggestion(
228+
block.span,
229+
"change this to",
230+
help,
231+
app,
232+
);
233+
}
234+
);
235+
}
236+
}
119237
}
120238
}

clippy_lints/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,6 @@ mod needless_continue;
227227
mod needless_else;
228228
mod needless_for_each;
229229
mod needless_if;
230-
mod needless_impls;
231230
mod needless_late_init;
232231
mod needless_parens_on_range_literals;
233232
mod needless_pass_by_value;

clippy_lints/src/needless_impls.rs

Lines changed: 0 additions & 145 deletions
This file was deleted.

tests/ui/bool_comparison.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#![allow(clippy::needless_if)]
44
#![warn(clippy::bool_comparison)]
5-
#![allow(clippy::needless_partial_ord_impl)]
5+
#![allow(clippy::incorrect_partial_ord_impl_on_ord_type)]
66

77
fn main() {
88
let x = true;

tests/ui/bool_comparison.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#![allow(clippy::needless_if)]
44
#![warn(clippy::bool_comparison)]
5-
#![allow(clippy::needless_partial_ord_impl)]
5+
#![allow(clippy::incorrect_partial_ord_impl_on_ord_type)]
66

77
fn main() {
88
let x = true;

tests/ui/derive.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
#![allow(clippy::incorrect_clone_impl_on_copy_type, dead_code)]
1+
#![allow(
2+
clippy::incorrect_clone_impl_on_copy_type,
3+
clippy::incorrect_partial_ord_impl_on_ord_type,
4+
dead_code
5+
)]
26
#![warn(clippy::expl_impl_clone_on_copy)]
37

48
#[derive(Copy)]

0 commit comments

Comments
 (0)