Do not store attrs in FnKind.

This commit is contained in:
Camille GILLOT 2020-11-27 09:24:42 +01:00
parent f5dc5dcca3
commit 8e816056a5
16 changed files with 51 additions and 70 deletions

View File

@ -101,29 +101,21 @@ fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>) {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum FnKind<'a> { pub enum FnKind<'a> {
/// `#[xxx] pub async/const/extern "Abi" fn foo()` /// `#[xxx] pub async/const/extern "Abi" fn foo()`
ItemFn(Ident, &'a Generics<'a>, FnHeader, &'a Visibility<'a>, &'a [Attribute]), ItemFn(Ident, &'a Generics<'a>, FnHeader, &'a Visibility<'a>),
/// `fn foo(&self)` /// `fn foo(&self)`
Method(Ident, &'a FnSig<'a>, Option<&'a Visibility<'a>>, &'a [Attribute]), Method(Ident, &'a FnSig<'a>, Option<&'a Visibility<'a>>),
/// `|x, y| {}` /// `|x, y| {}`
Closure(&'a [Attribute]), Closure,
} }
impl<'a> FnKind<'a> { impl<'a> FnKind<'a> {
pub fn attrs(&self) -> &'a [Attribute] {
match *self {
FnKind::ItemFn(.., attrs) => attrs,
FnKind::Method(.., attrs) => attrs,
FnKind::Closure(attrs) => attrs,
}
}
pub fn header(&self) -> Option<&FnHeader> { pub fn header(&self) -> Option<&FnHeader> {
match *self { match *self {
FnKind::ItemFn(_, _, ref header, _, _) => Some(header), FnKind::ItemFn(_, _, ref header, _) => Some(header),
FnKind::Method(_, ref sig, _, _) => Some(&sig.header), FnKind::Method(_, ref sig, _) => Some(&sig.header),
FnKind::Closure(_) => None, FnKind::Closure => None,
} }
} }
} }
@ -579,7 +571,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
visitor.visit_nested_body(body); visitor.visit_nested_body(body);
} }
ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn( ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn(
FnKind::ItemFn(item.ident, generics, sig.header, &item.vis, &item.attrs), FnKind::ItemFn(item.ident, generics, sig.header, &item.vis),
&sig.decl, &sig.decl,
body_id, body_id,
item.span, item.span,
@ -940,7 +932,7 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
FnKind::ItemFn(_, generics, ..) => { FnKind::ItemFn(_, generics, ..) => {
visitor.visit_generics(generics); visitor.visit_generics(generics);
} }
FnKind::Method(..) | FnKind::Closure(_) => {} FnKind::Method(..) | FnKind::Closure => {}
} }
} }
@ -977,7 +969,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
} }
TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
visitor.visit_fn( visitor.visit_fn(
FnKind::Method(trait_item.ident, sig, None, &trait_item.attrs), FnKind::Method(trait_item.ident, sig, None),
&sig.decl, &sig.decl,
body_id, body_id,
trait_item.span, trait_item.span,
@ -1027,7 +1019,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
} }
ImplItemKind::Fn(ref sig, body_id) => { ImplItemKind::Fn(ref sig, body_id) => {
visitor.visit_fn( visitor.visit_fn(
FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), &impl_item.attrs), FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis)),
&sig.decl, &sig.decl,
body_id, body_id,
impl_item.span, impl_item.span,
@ -1162,7 +1154,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
} }
ExprKind::Closure(_, ref function_declaration, body, _fn_decl_span, _gen) => visitor ExprKind::Closure(_, ref function_declaration, body, _fn_decl_span, _gen) => visitor
.visit_fn( .visit_fn(
FnKind::Closure(&expression.attrs), FnKind::Closure,
function_declaration, function_declaration,
body, body,
expression.span, expression.span,

View File

@ -400,14 +400,15 @@ fn check_fn(
} }
_ => (), _ => (),
}, },
FnKind::ItemFn(ident, _, header, _, attrs) => { FnKind::ItemFn(ident, _, header, _) => {
let attrs = cx.tcx.hir().attrs(id);
// Skip foreign-ABI #[no_mangle] functions (Issue #31924) // Skip foreign-ABI #[no_mangle] functions (Issue #31924)
if header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle) { if header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle) {
return; return;
} }
self.check_snake_case(cx, "function", ident); self.check_snake_case(cx, "function", ident);
} }
FnKind::Closure(_) => (), FnKind::Closure => (),
} }
} }

View File

@ -12,7 +12,6 @@
//! for the `Code` associated with a particular NodeId. //! for the `Code` associated with a particular NodeId.
use crate::hir::map::Map; use crate::hir::map::Map;
use rustc_ast::Attribute;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::intravisit::FnKind; use rustc_hir::intravisit::FnKind;
use rustc_hir::{Expr, FnDecl, Node}; use rustc_hir::{Expr, FnDecl, Node};
@ -105,7 +104,6 @@ struct ItemFnParts<'a> {
body: hir::BodyId, body: hir::BodyId,
id: hir::HirId, id: hir::HirId,
span: Span, span: Span,
attrs: &'a [Attribute],
} }
/// These are all the components one can extract from a closure expr /// These are all the components one can extract from a closure expr
@ -115,18 +113,11 @@ struct ClosureParts<'a> {
body: hir::BodyId, body: hir::BodyId,
id: hir::HirId, id: hir::HirId,
span: Span, span: Span,
attrs: &'a [Attribute],
} }
impl<'a> ClosureParts<'a> { impl<'a> ClosureParts<'a> {
fn new( fn new(d: &'a FnDecl<'a>, b: hir::BodyId, id: hir::HirId, s: Span) -> Self {
d: &'a FnDecl<'a>, ClosureParts { decl: d, body: b, id, span: s }
b: hir::BodyId,
id: hir::HirId,
s: Span,
attrs: &'a [Attribute],
) -> Self {
ClosureParts { decl: d, body: b, id, span: s, attrs }
} }
} }
@ -146,7 +137,7 @@ pub fn from_node(node: Node<'_>) -> Option<FnLikeNode<'_>> {
pub fn body(self) -> hir::BodyId { pub fn body(self) -> hir::BodyId {
self.handle( self.handle(
|i: ItemFnParts<'a>| i.body, |i: ItemFnParts<'a>| i.body,
|_, _, _: &'a hir::FnSig<'a>, _, body: hir::BodyId, _, _| body, |_, _, _: &'a hir::FnSig<'a>, _, body: hir::BodyId, _| body,
|c: ClosureParts<'a>| c.body, |c: ClosureParts<'a>| c.body,
) )
} }
@ -154,7 +145,7 @@ pub fn body(self) -> hir::BodyId {
pub fn decl(self) -> &'a FnDecl<'a> { pub fn decl(self) -> &'a FnDecl<'a> {
self.handle( self.handle(
|i: ItemFnParts<'a>| &*i.decl, |i: ItemFnParts<'a>| &*i.decl,
|_, _, sig: &'a hir::FnSig<'a>, _, _, _, _| &sig.decl, |_, _, sig: &'a hir::FnSig<'a>, _, _, _| &sig.decl,
|c: ClosureParts<'a>| c.decl, |c: ClosureParts<'a>| c.decl,
) )
} }
@ -162,7 +153,7 @@ pub fn decl(self) -> &'a FnDecl<'a> {
pub fn span(self) -> Span { pub fn span(self) -> Span {
self.handle( self.handle(
|i: ItemFnParts<'_>| i.span, |i: ItemFnParts<'_>| i.span,
|_, _, _: &'a hir::FnSig<'a>, _, _, span, _| span, |_, _, _: &'a hir::FnSig<'a>, _, _, span| span,
|c: ClosureParts<'_>| c.span, |c: ClosureParts<'_>| c.span,
) )
} }
@ -170,7 +161,7 @@ pub fn span(self) -> Span {
pub fn id(self) -> hir::HirId { pub fn id(self) -> hir::HirId {
self.handle( self.handle(
|i: ItemFnParts<'_>| i.id, |i: ItemFnParts<'_>| i.id,
|id, _, _: &'a hir::FnSig<'a>, _, _, _, _| id, |id, _, _: &'a hir::FnSig<'a>, _, _, _| id,
|c: ClosureParts<'_>| c.id, |c: ClosureParts<'_>| c.id,
) )
} }
@ -189,12 +180,11 @@ pub fn unsafety(self) -> hir::Unsafety {
pub fn kind(self) -> FnKind<'a> { pub fn kind(self) -> FnKind<'a> {
let item = |p: ItemFnParts<'a>| -> FnKind<'a> { let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
FnKind::ItemFn(p.ident, p.generics, p.header, p.vis, p.attrs) FnKind::ItemFn(p.ident, p.generics, p.header, p.vis)
};
let closure = |c: ClosureParts<'a>| FnKind::Closure(c.attrs);
let method = |_, ident: Ident, sig: &'a hir::FnSig<'a>, vis, _, _, attrs| {
FnKind::Method(ident, sig, vis, attrs)
}; };
let closure = |_: ClosureParts<'a>| FnKind::Closure;
let method =
|_, ident: Ident, sig: &'a hir::FnSig<'a>, vis, _, _| FnKind::Method(ident, sig, vis);
self.handle(item, method, closure) self.handle(item, method, closure)
} }
@ -208,7 +198,6 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A
Option<&'a hir::Visibility<'a>>, Option<&'a hir::Visibility<'a>>,
hir::BodyId, hir::BodyId,
Span, Span,
&'a [Attribute],
) -> A, ) -> A,
C: FnOnce(ClosureParts<'a>) -> A, C: FnOnce(ClosureParts<'a>) -> A,
{ {
@ -221,7 +210,6 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A
body: block, body: block,
vis: &i.vis, vis: &i.vis,
span: i.span, span: i.span,
attrs: &i.attrs,
header: sig.header, header: sig.header,
generics, generics,
}), }),
@ -229,19 +217,19 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A
}, },
Node::TraitItem(ti) => match ti.kind { Node::TraitItem(ti) => match ti.kind {
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
method(ti.hir_id(), ti.ident, sig, None, body, ti.span, &ti.attrs) method(ti.hir_id(), ti.ident, sig, None, body, ti.span)
} }
_ => bug!("trait method FnLikeNode that is not fn-like"), _ => bug!("trait method FnLikeNode that is not fn-like"),
}, },
Node::ImplItem(ii) => match ii.kind { Node::ImplItem(ii) => match ii.kind {
hir::ImplItemKind::Fn(ref sig, body) => { hir::ImplItemKind::Fn(ref sig, body) => {
method(ii.hir_id(), ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs) method(ii.hir_id(), ii.ident, sig, Some(&ii.vis), body, ii.span)
} }
_ => bug!("impl method FnLikeNode that is not fn-like"), _ => bug!("impl method FnLikeNode that is not fn-like"),
}, },
Node::Expr(e) => match e.kind { Node::Expr(e) => match e.kind {
hir::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => { hir::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => {
closure(ClosureParts::new(&decl, block, e.hir_id, e.span, &e.attrs)) closure(ClosureParts::new(&decl, block, e.hir_id, e.span))
} }
_ => bug!("expr FnLikeNode that is not fn-like"), _ => bug!("expr FnLikeNode that is not fn-like"),
}, },

View File

@ -15,7 +15,7 @@
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) { if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) {
if let FnKind::Closure(_) = fn_like_node.kind() { if let FnKind::Closure = fn_like_node.kind() {
// closures can't recur, so they don't matter. // closures can't recur, so they don't matter.
return; return;
} }

View File

@ -46,7 +46,7 @@ fn visit_fn(
let fn_header; let fn_header;
match fk { match fk {
FnKind::Closure(..) => { FnKind::Closure => {
// Closures with a naked attribute are rejected during attribute // Closures with a naked attribute are rejected during attribute
// check. Don't validate them any further. // check. Don't validate them any further.
return; return;
@ -62,7 +62,8 @@ fn visit_fn(
} }
} }
let naked = fk.attrs().iter().any(|attr| attr.has_name(sym::naked)); let attrs = self.tcx.hir().attrs(hir_id);
let naked = attrs.iter().any(|attr| attr.has_name(sym::naked));
if naked { if naked {
let body = self.tcx.hir().body(body_id); let body = self.tcx.hir().body(body_id);
check_abi(self.tcx, hir_id, fn_header.abi, ident_span); check_abi(self.tcx, hir_id, fn_header.abi, ident_span);

View File

@ -354,7 +354,7 @@ fn visit_fn(
hir_id: hir::HirId, hir_id: hir::HirId,
) { ) {
assert!( assert!(
matches!(fk, intravisit::FnKind::Closure(..)), matches!(fk, intravisit::FnKind::Closure),
"visit_fn invoked for something other than a closure" "visit_fn invoked for something other than a closure"
); );

View File

@ -76,8 +76,8 @@ fn check<'tcx>(
if rust_cc > self.limit.limit() { if rust_cc > self.limit.limit() {
let fn_span = match kind { let fn_span = match kind {
FnKind::ItemFn(ident, _, _, _, _) | FnKind::Method(ident, _, _, _) => ident.span, FnKind::ItemFn(ident, _, _, _) | FnKind::Method(ident, _, _) => ident.span,
FnKind::Closure(_) => { FnKind::Closure => {
let header_span = body_span.with_hi(decl.output.span().lo()); let header_span = body_span.with_hi(decl.output.span().lo());
let pos = snippet_opt(cx, header_span).and_then(|snip| { let pos = snippet_opt(cx, header_span).and_then(|snip| {
let low_offset = snip.find('|')?; let low_offset = snip.find('|')?;

View File

@ -251,9 +251,9 @@ fn check_fn(
hir_id: hir::HirId, hir_id: hir::HirId,
) { ) {
let unsafety = match kind { let unsafety = match kind {
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _, _) => unsafety, intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
intravisit::FnKind::Method(_, sig, _, _) => sig.header.unsafety, intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
intravisit::FnKind::Closure(_) => return, intravisit::FnKind::Closure => return,
}; };
// don't warn for implementations, it's not their fault // don't warn for implementations, it's not their fault
@ -267,9 +267,8 @@ fn check_fn(
.. ..
}, },
_, _,
_,
) )
| intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _, _) => { | intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _) => {
self.check_arg_number(cx, decl, span.with_hi(decl.output.span().hi())) self.check_arg_number(cx, decl, span.with_hi(decl.output.span().hi()))
}, },
_ => {}, _ => {},

View File

@ -58,7 +58,7 @@ fn check_fn(
_: Span, _: Span,
hir_id: HirId, hir_id: HirId,
) { ) {
if let FnKind::Closure(_) = kind { if let FnKind::Closure = kind {
return; return;
} }
let ret_ty = utils::return_ty(cx, hir_id); let ret_ty = utils::return_ty(cx, hir_id);

View File

@ -278,7 +278,7 @@ fn check_fn(
span: Span, span: Span,
_: HirId, _: HirId,
) { ) {
if let FnKind::Closure(_) = k { if let FnKind::Closure = k {
// Does not apply to closures // Does not apply to closures
return; return;
} }

View File

@ -133,7 +133,7 @@ fn check_fn(
return; return;
} }
}, },
FnKind::Closure(..) => return, FnKind::Closure => return,
} }
let mir = cx.tcx.optimized_mir(def_id); let mir = cx.tcx.optimized_mir(def_id);

View File

@ -80,13 +80,14 @@ fn check_fn(
} }
match kind { match kind {
FnKind::ItemFn(.., header, _, attrs) => { FnKind::ItemFn(.., header, _) => {
let attrs = cx.tcx.hir().attrs(hir_id);
if header.abi != Abi::Rust || requires_exact_signature(attrs) { if header.abi != Abi::Rust || requires_exact_signature(attrs) {
return; return;
} }
}, },
FnKind::Method(..) => (), FnKind::Method(..) => (),
FnKind::Closure(..) => return, FnKind::Closure => return,
} }
// Exclude non-inherent impls // Exclude non-inherent impls

View File

@ -43,9 +43,7 @@ fn check_fn(
span: Span, span: Span,
hir_id: hir::HirId, hir_id: hir::HirId,
) { ) {
if !matches!(fn_kind, FnKind::Closure(_)) if !matches!(fn_kind, FnKind::Closure) && is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::result_type) {
&& is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::result_type)
{
lint_impl_body(cx, span, body); lint_impl_body(cx, span, body);
} }
} }

View File

@ -224,10 +224,11 @@ fn check_fn(
} }
match kind { match kind {
FnKind::ItemFn(.., header, _, attrs) => { FnKind::ItemFn(.., header, _) => {
if header.abi != Abi::Rust { if header.abi != Abi::Rust {
return; return;
} }
let attrs = cx.tcx.hir().attrs(hir_id);
for a in attrs { for a in attrs {
if let Some(meta_items) = a.meta_item_list() { if let Some(meta_items) = a.meta_item_list() {
if a.has_name(sym::proc_macro_derive) if a.has_name(sym::proc_macro_derive)
@ -239,7 +240,7 @@ fn check_fn(
} }
}, },
FnKind::Method(..) => (), FnKind::Method(..) => (),
FnKind::Closure(..) => return, FnKind::Closure => return,
} }
// Exclude non-inherent impls // Exclude non-inherent impls

View File

@ -131,7 +131,7 @@ fn check_fn(
_: HirId, _: HirId,
) { ) {
match kind { match kind {
FnKind::Closure(_) => { FnKind::Closure => {
// when returning without value in closure, replace this `return` // when returning without value in closure, replace this `return`
// with an empty block to prevent invalid suggestion (see #6501) // with an empty block to prevent invalid suggestion (see #6501)
let replacement = if let ExprKind::Ret(None) = &body.value.kind { let replacement = if let ExprKind::Ret(None) = &body.value.kind {

View File

@ -66,12 +66,12 @@ fn check_fn(
) { ) {
// Abort if public function/method or closure. // Abort if public function/method or closure.
match fn_kind { match fn_kind {
FnKind::ItemFn(.., visibility, _) | FnKind::Method(.., Some(visibility), _) => { FnKind::ItemFn(.., visibility) | FnKind::Method(.., Some(visibility)) => {
if visibility.node.is_pub() { if visibility.node.is_pub() {
return; return;
} }
}, },
FnKind::Closure(..) => return, FnKind::Closure => return,
_ => (), _ => (),
} }