Fix: cmp_owned wrongly unmangled macros (#16331)

Closes rust-lang/rust-clippy#16322

changelog: [`cmp_owned`] fix wrongly unmangled macros
This commit is contained in:
dswij 2026-01-03 16:13:07 +00:00 committed by GitHub
commit 48821414b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 87 additions and 37 deletions

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::res::MaybeQPath;
use clippy_utils::source::snippet;
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{implements_trait, is_copy};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
@ -94,51 +94,37 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
return;
}
let arg_snip = snippet(cx, arg_span, "..");
let expr_snip;
let eq_impl;
if with_deref.is_implemented() && !arg_ty.peel_refs().is_str() {
expr_snip = format!("*{arg_snip}");
eq_impl = with_deref;
let mut applicability = Applicability::MachineApplicable;
let (arg_snip, _) = snippet_with_context(cx, arg_span, expr.span.ctxt(), "..", &mut applicability);
let (expr_snip, eq_impl) = if with_deref.is_implemented() && !arg_ty.peel_refs().is_str() {
(format!("*{arg_snip}"), with_deref)
} else {
expr_snip = arg_snip.to_string();
eq_impl = without_deref;
}
(arg_snip.to_string(), without_deref)
};
let span;
let hint;
if (eq_impl.ty_eq_other && left) || (eq_impl.other_eq_ty && !left) {
span = expr.span;
hint = expr_snip;
let (span, hint) = if (eq_impl.ty_eq_other && left) || (eq_impl.other_eq_ty && !left) {
(expr.span, expr_snip)
} else {
span = expr.span.to(other.span);
let span = expr.span.to(other.span);
let cmp_span = if other.span < expr.span {
other.span.between(expr.span)
} else {
expr.span.between(other.span)
};
if eq_impl.ty_eq_other {
hint = format!(
"{expr_snip}{}{}",
snippet(cx, cmp_span, ".."),
snippet(cx, other.span, "..")
);
} else {
hint = format!(
"{}{}{expr_snip}",
snippet(cx, other.span, ".."),
snippet(cx, cmp_span, "..")
);
}
}
diag.span_suggestion(
span,
"try",
hint,
Applicability::MachineApplicable, // snippet
);
let (cmp_snippet, _) = snippet_with_context(cx, cmp_span, expr.span.ctxt(), "..", &mut applicability);
let (other_snippet, _) =
snippet_with_context(cx, other.span, expr.span.ctxt(), "..", &mut applicability);
if eq_impl.ty_eq_other {
(span, format!("{expr_snip}{cmp_snippet}{other_snippet}"))
} else {
(span, format!("{other_snippet}{cmp_snippet}{expr_snip}"))
}
};
diag.span_suggestion(span, "try", hint, applicability);
},
);
}

View file

@ -83,3 +83,32 @@ fn issue_8103() {
let _ = foo1 == foo2;
//~^ cmp_owned
}
macro_rules! issue16322_macro_generator {
($locale:ident) => {
mod $locale {
macro_rules! _make {
($token:tt) => {
stringify!($token)
};
}
pub(crate) use _make;
}
macro_rules! t {
($token:tt) => {
crate::$locale::_make!($token)
};
}
};
}
issue16322_macro_generator!(de);
fn issue16322(item: String) {
if item == t!(frohes_neu_Jahr) {
//~^ cmp_owned
println!("Ja!");
}
}

View file

@ -83,3 +83,32 @@ fn issue_8103() {
let _ = foo1 == foo2.to_owned();
//~^ cmp_owned
}
macro_rules! issue16322_macro_generator {
($locale:ident) => {
mod $locale {
macro_rules! _make {
($token:tt) => {
stringify!($token)
};
}
pub(crate) use _make;
}
macro_rules! t {
($token:tt) => {
crate::$locale::_make!($token)
};
}
};
}
issue16322_macro_generator!(de);
fn issue16322(item: String) {
if item == t!(frohes_neu_Jahr).to_string() {
//~^ cmp_owned
println!("Ja!");
}
}

View file

@ -49,5 +49,11 @@ error: this creates an owned instance just for comparison
LL | let _ = foo1 == foo2.to_owned();
| ^^^^^^^^^^^^^^^ help: try: `foo2`
error: aborting due to 8 previous errors
error: this creates an owned instance just for comparison
--> tests/ui/cmp_owned/with_suggestion.rs:110:16
|
LL | if item == t!(frohes_neu_Jahr).to_string() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t!(frohes_neu_Jahr)`
error: aborting due to 9 previous errors