fix(needless_maybe_sized): don't lint in proc-macro-generated code (#15629)

Fixes https://github.com/rust-lang/rust-clippy/issues/13360

changelog: [`needless_maybe_sized`]: don't lint in proc-macro-generated
code
This commit is contained in:
Jason Newcomb
2026-02-23 01:09:15 +00:00
committed by GitHub
4 changed files with 64 additions and 4 deletions
+3
View File
@@ -1,4 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use rustc_errors::Applicability;
use rustc_hir::def_id::{DefId, DefIdMap};
use rustc_hir::{BoundPolarity, GenericBound, Generics, PolyTraitRef, TraitBoundModifiers, WherePredicateKind};
@@ -34,6 +35,7 @@
declare_lint_pass!(NeedlessMaybeSized => [NEEDLESS_MAYBE_SIZED]);
#[expect(clippy::struct_field_names)]
#[derive(Debug)]
struct Bound<'tcx> {
/// The [`DefId`] of the type parameter the bound refers to
param: DefId,
@@ -127,6 +129,7 @@ fn check_generics(&mut self, cx: &LateContext<'_>, generics: &Generics<'_>) {
if bound.trait_bound.modifiers == TraitBoundModifiers::NONE
&& let Some(sized_bound) = maybe_sized_params.get(&bound.param)
&& let Some(path) = path_to_sized_bound(cx, bound.trait_bound)
&& !is_from_proc_macro(cx, bound.trait_bound)
{
span_lint_and_then(
cx,
+43 -4
View File
@@ -21,10 +21,10 @@
use rustc_ast::token::CommentKind;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl,
ImplItem, ImplItemImplKind, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path,
QPath, Safety, TraitImplHeader, TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData,
YieldSource,
Block, BlockCheckMode, Body, BoundConstness, BoundPolarity, Closure, Destination, Expr, ExprKind, FieldDef,
FnHeader, FnRetTy, HirId, Impl, ImplItem, ImplItemImplKind, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource,
MatchSource, MutTy, Node, Path, PolyTraitRef, QPath, Safety, TraitBoundModifiers, TraitImplHeader, TraitItem,
TraitItemKind, TraitRef, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
};
use rustc_lint::{EarlyContext, LateContext, LintContext};
use rustc_middle::ty::TyCtxt;
@@ -541,6 +541,44 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) {
}
}
// NOTE: can't `impl WithSearchPat for TraitRef`, because `TraitRef` doesn't have a `span` field
// (nor a method)
fn trait_ref_search_pat(trait_ref: &TraitRef<'_>) -> (Pat, Pat) {
path_search_pat(trait_ref.path)
}
fn poly_trait_ref_search_pat(poly_trait_ref: &PolyTraitRef<'_>) -> (Pat, Pat) {
// NOTE: unfortunately we can't use `bound_generic_params` to see whether the pattern starts with
// `for<..>`, because if it's empty, we could have either `for<>` (nothing bound), or
// no `for` at all
let PolyTraitRef {
modifiers: TraitBoundModifiers { constness, polarity },
trait_ref,
..
} = poly_trait_ref;
let trait_ref_search_pat = trait_ref_search_pat(trait_ref);
#[expect(
clippy::unnecessary_lazy_evaluations,
reason = "the closure in `or_else` has `match polarity`, which isn't free"
)]
let start = match constness {
BoundConstness::Never => None,
BoundConstness::Maybe(_) => Some(Pat::Str("[const]")),
BoundConstness::Always(_) => Some(Pat::Str("const")),
}
.or_else(|| match polarity {
BoundPolarity::Negative(_) => Some(Pat::Str("!")),
BoundPolarity::Maybe(_) => Some(Pat::Str("?")),
BoundPolarity::Positive => None,
})
.unwrap_or(trait_ref_search_pat.0);
let end = trait_ref_search_pat.1;
(start, end)
}
fn ident_search_pat(ident: Ident) -> (Pat, Pat) {
(Pat::Sym(ident.name), Pat::Sym(ident.name))
}
@@ -573,6 +611,7 @@ fn span(&self) -> Span {
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ident) => ident_search_pat(*self));
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Lit) => lit_search_pat(&self.node));
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Path<'_>) => path_search_pat(self));
impl_with_search_pat!((_cx: LateContext<'tcx>, self: PolyTraitRef<'_>) => poly_trait_ref_search_pat(self));
impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: Attribute) => attr_search_pat(self));
impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: ast::Ty) => ast_ty_search_pat(self));
+9
View File
@@ -133,4 +133,13 @@ struct InDerive<T: ?Sized> {
struct Refined<T: ?Sized>(T);
impl<T: Sized> Refined<T> {}
// in proc-macros
fn issue13360() {
#[derive(serde::Serialize)]
#[serde(bound = "T: A")]
struct Foo<T: ?Sized> {
t: std::marker::PhantomData<T>,
}
}
fn main() {}
+9
View File
@@ -136,4 +136,13 @@ struct InDerive<T: ?Sized> {
struct Refined<T: ?Sized>(T);
impl<T: Sized> Refined<T> {}
// in proc-macros
fn issue13360() {
#[derive(serde::Serialize)]
#[serde(bound = "T: A")]
struct Foo<T: ?Sized> {
t: std::marker::PhantomData<T>,
}
}
fn main() {}