Skip to content

Commit 1c8e61e

Browse files
committed
fix(needless_maybe_sized): don't lint in proc-macro-generated code
1 parent 4b236fc commit 1c8e61e

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
#[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,
@@ -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;
@@ -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)