Skip to content

Commit 05638eb

Browse files
committed
fix(needless_maybe_sized): don't lint in proc-macro-generated code
1 parent c1f6124 commit 05638eb

File tree

4 files changed

+60
-4
lines changed

4 files changed

+60
-4
lines changed

clippy_lints/src/needless_maybe_sized.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2+
use clippy_utils::is_from_proc_macro;
23
use rustc_errors::Applicability;
34
use rustc_hir::def_id::{DefId, DefIdMap};
45
use rustc_hir::{BoundPolarity, GenericBound, Generics, PolyTraitRef, TraitBoundModifiers, WherePredicateKind};
@@ -34,6 +35,7 @@ declare_clippy_lint! {
3435
declare_lint_pass!(NeedlessMaybeSized => [NEEDLESS_MAYBE_SIZED]);
3536

3637
#[expect(clippy::struct_field_names)]
38+
#[derive(Debug)]
3739
struct Bound<'tcx> {
3840
/// The [`DefId`] of the type parameter the bound refers to
3941
param: DefId,
@@ -127,6 +129,7 @@ impl LateLintPass<'_> for NeedlessMaybeSized {
127129
if bound.trait_bound.modifiers == TraitBoundModifiers::NONE
128130
&& let Some(sized_bound) = maybe_sized_params.get(&bound.param)
129131
&& let Some(path) = path_to_sized_bound(cx, bound.trait_bound)
132+
&& !is_from_proc_macro(cx, bound.trait_bound)
130133
{
131134
span_lint_and_then(
132135
cx,

clippy_utils/src/check_proc_macro.rs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ use rustc_ast::ast::{
2121
use rustc_ast::token::CommentKind;
2222
use rustc_hir::intravisit::FnKind;
2323
use rustc_hir::{
24-
Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl,
25-
ImplItem, ImplItemImplKind, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path,
26-
QPath, Safety, TraitImplHeader, TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData,
27-
YieldSource,
24+
Block, BlockCheckMode, Body, BoundConstness, BoundPolarity, Closure, Destination, Expr, ExprKind, FieldDef,
25+
FnHeader, FnRetTy, HirId, Impl, ImplItem, ImplItemImplKind, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource,
26+
MatchSource, MutTy, Node, Path, PolyTraitRef, QPath, Safety, TraitBoundModifiers, TraitImplHeader, TraitItem,
27+
TraitItemKind, TraitRef, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
2828
};
2929
use rustc_lint::{EarlyContext, LateContext, LintContext};
3030
use rustc_middle::ty::TyCtxt;
@@ -537,6 +537,40 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) {
537537
}
538538
}
539539

540+
// NOTE: can't `impl WithSearchPat for TraitRef`, because `TraitRef` doesn't have a `span` field
541+
// (nor a method)
542+
fn trait_ref_search_pat(trait_ref: &TraitRef<'_>) -> (Pat, Pat) {
543+
path_search_pat(trait_ref.path)
544+
}
545+
546+
fn poly_trait_ref_search_pat(poly_trait_ref: &PolyTraitRef<'_>) -> (Pat, Pat) {
547+
// NOTE: unfortunately we can't use `bound_generic_params` to see whether the pattern starts with
548+
// `for<..>`, because if it's empty, we could have either `for<>` (nothing bound), or
549+
// no `for` at all
550+
let PolyTraitRef {
551+
modifiers: TraitBoundModifiers { constness, polarity },
552+
trait_ref,
553+
..
554+
} = poly_trait_ref;
555+
556+
let trait_ref_search_pat = trait_ref_search_pat(trait_ref);
557+
558+
let start = match constness {
559+
BoundConstness::Never => None,
560+
BoundConstness::Maybe(_) => Some(Pat::Str("[const]")),
561+
BoundConstness::Always(_) => Some(Pat::Str("const")),
562+
}
563+
.or(match polarity {
564+
BoundPolarity::Negative(_) => Some(Pat::Str("!")),
565+
BoundPolarity::Maybe(_) => Some(Pat::Str("?")),
566+
BoundPolarity::Positive => None,
567+
})
568+
.unwrap_or(trait_ref_search_pat.0);
569+
let end = trait_ref_search_pat.1;
570+
571+
(start, end)
572+
}
573+
540574
fn ident_search_pat(ident: Ident) -> (Pat, Pat) {
541575
(Pat::Sym(ident.name), Pat::Sym(ident.name))
542576
}
@@ -569,6 +603,7 @@ impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ty<'_>) => ty_search_pat(se
569603
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ident) => ident_search_pat(*self));
570604
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Lit) => lit_search_pat(&self.node));
571605
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Path<'_>) => path_search_pat(self));
606+
impl_with_search_pat!((_cx: LateContext<'tcx>, self: PolyTraitRef<'_>) => poly_trait_ref_search_pat(self));
572607

573608
impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: Attribute) => attr_search_pat(self));
574609
impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: ast::Ty) => ast_ty_search_pat(self));

tests/ui/needless_maybe_sized.fixed

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,13 @@ struct InDerive<T: ?Sized> {
133133
struct Refined<T: ?Sized>(T);
134134
impl<T: Sized> Refined<T> {}
135135

136+
// in proc-macros
137+
fn issue13360() {
138+
#[derive(serde::Serialize)]
139+
#[serde(bound = "T: A")]
140+
struct Foo<T: ?Sized> {
141+
t: std::marker::PhantomData<T>,
142+
}
143+
}
144+
136145
fn main() {}

tests/ui/needless_maybe_sized.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,13 @@ struct InDerive<T: ?Sized> {
136136
struct Refined<T: ?Sized>(T);
137137
impl<T: Sized> Refined<T> {}
138138

139+
// in proc-macros
140+
fn issue13360() {
141+
#[derive(serde::Serialize)]
142+
#[serde(bound = "T: A")]
143+
struct Foo<T: ?Sized> {
144+
t: std::marker::PhantomData<T>,
145+
}
146+
}
147+
139148
fn main() {}

0 commit comments

Comments
 (0)