mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-23 02:27:39 +03:00
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:
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
Reference in New Issue
Block a user