Skip to content

Commit 1fc12dc

Browse files
committed
fix(needless_maybe_sized): don't lint in proc-macro-generated code
1 parent 8a5dc7c commit 1fc12dc

File tree

4 files changed

+64
-8
lines changed

4 files changed

+64
-8
lines changed

clippy_lints/src/needless_maybe_sized.rs

Lines changed: 7 additions & 4 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
#[allow(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,
@@ -46,7 +48,7 @@ struct Bound<'tcx> {
4648
}
4749

4850
/// Finds all of the [`Bound`]s that refer to a type parameter and are not from a macro expansion
49-
fn type_param_bounds<'tcx>(generics: &'tcx Generics<'tcx>) -> impl Iterator<Item = Bound<'tcx>> {
51+
fn type_param_bounds<'tcx>(cx: &LateContext<'_>, generics: &'tcx Generics<'tcx>) -> impl Iterator<Item = Bound<'tcx>> {
5052
generics
5153
.predicates
5254
.iter()
@@ -73,7 +75,8 @@ fn type_param_bounds<'tcx>(generics: &'tcx Generics<'tcx>) -> impl Iterator<Item
7375
}),
7476
GenericBound::Outlives(_) | GenericBound::Use(..) => None,
7577
})
76-
.filter(|bound| !bound.trait_bound.span.from_expansion()),
78+
.filter(|bound| !bound.trait_bound.span.from_expansion())
79+
.filter(|bound| !is_from_proc_macro(cx, bound.trait_bound)),
7780
)
7881
})
7982
.flatten()
@@ -115,15 +118,15 @@ impl LateLintPass<'_> for NeedlessMaybeSized {
115118
return;
116119
};
117120

118-
let maybe_sized_params: DefIdMap<_> = type_param_bounds(generics)
121+
let maybe_sized_params: DefIdMap<_> = type_param_bounds(cx, generics)
119122
.filter(|bound| {
120123
bound.trait_bound.trait_ref.trait_def_id() == Some(sized_trait)
121124
&& matches!(bound.trait_bound.modifiers.polarity, BoundPolarity::Maybe(_))
122125
})
123126
.map(|bound| (bound.param, bound))
124127
.collect();
125128

126-
for bound in type_param_bounds(generics) {
129+
for bound in type_param_bounds(cx, generics) {
127130
if bound.trait_bound.modifiers == TraitBoundModifiers::NONE
128131
&& let Some(sized_bound) = maybe_sized_params.get(&bound.param)
129132
&& let Some(path) = path_to_sized_bound(cx, bound.trait_bound)

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;
@@ -540,6 +540,40 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) {
540540
}
541541
}
542542

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

576611
impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: Attribute) => attr_search_pat(self));
577612
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)