use front::map::{self, Node};
use syntax::abi;
use rustc_front::hir::{Block, FnDecl};
-use syntax::ast::{Name, NodeId};
+use syntax::ast::{Attribute, Name, NodeId};
+use syntax::attr::ThinAttributesExt;
use rustc_front::hir as ast;
use syntax::codemap::Span;
use rustc_front::intravisit::FnKind;
generics: &'a ast::Generics,
body: &'a Block,
id: NodeId,
- span: Span
+ span: Span,
+ attrs: &'a [Attribute],
}
/// These are all the components one can extract from a closure expr
decl: &'a FnDecl,
body: &'a Block,
id: NodeId,
- span: Span
+ span: Span,
+ attrs: &'a [Attribute],
}
impl<'a> ClosureParts<'a> {
- fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span) -> ClosureParts<'a> {
- ClosureParts { decl: d, body: b, id: id, span: s }
+ fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
+ ClosureParts { decl: d, body: b, id: id, span: s, attrs: attrs }
}
}
pub fn body(self) -> &'a Block {
self.handle(|i: ItemFnParts<'a>| &*i.body,
- |_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _| body,
+ |_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _, _| body,
|c: ClosureParts<'a>| c.body)
}
pub fn decl(self) -> &'a FnDecl {
self.handle(|i: ItemFnParts<'a>| &*i.decl,
- |_, _, sig: &'a ast::MethodSig, _, _, _| &sig.decl,
+ |_, _, sig: &'a ast::MethodSig, _, _, _, _| &sig.decl,
|c: ClosureParts<'a>| c.decl)
}
pub fn span(self) -> Span {
self.handle(|i: ItemFnParts| i.span,
- |_, _, _: &'a ast::MethodSig, _, _, span| span,
+ |_, _, _: &'a ast::MethodSig, _, _, span, _| span,
|c: ClosureParts| c.span)
}
pub fn id(self) -> NodeId {
self.handle(|i: ItemFnParts| i.id,
- |id, _, _: &'a ast::MethodSig, _, _, _| id,
+ |id, _, _: &'a ast::MethodSig, _, _, _, _| id,
|c: ClosureParts| c.id)
}
pub fn kind(self) -> FnKind<'a> {
let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
- FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis)
+ FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis, p.attrs)
};
- let closure = |_: ClosureParts| {
- FnKind::Closure
+ let closure = |c: ClosureParts<'a>| {
+ FnKind::Closure(c.attrs)
};
- let method = |_, name: Name, sig: &'a ast::MethodSig, vis, _, _| {
- FnKind::Method(name, sig, vis)
+ let method = |_, name: Name, sig: &'a ast::MethodSig, vis, _, _, attrs| {
+ FnKind::Method(name, sig, vis, attrs)
};
self.handle(item, method, closure)
}
&'a ast::MethodSig,
Option<ast::Visibility>,
&'a ast::Block,
- Span)
+ Span,
+ &'a [Attribute])
-> A,
C: FnOnce(ClosureParts<'a>) -> A,
{
abi: abi,
vis: i.vis,
constness: constness,
- span: i.span
+ span: i.span,
+ attrs: &i.attrs,
}),
_ => panic!("item FnLikeNode that is not fn-like"),
},
map::NodeTraitItem(ti) => match ti.node {
ast::MethodTraitItem(ref sig, Some(ref body)) => {
- method(ti.id, ti.name, sig, None, body, ti.span)
+ method(ti.id, ti.name, sig, None, body, ti.span, &ti.attrs)
}
_ => panic!("trait method FnLikeNode that is not fn-like"),
},
map::NodeImplItem(ii) => {
match ii.node {
ast::ImplItemKind::Method(ref sig, ref body) => {
- method(ii.id, ii.name, sig, Some(ii.vis), body, ii.span)
+ method(ii.id, ii.name, sig, Some(ii.vis), body, ii.span, &ii.attrs)
}
_ => {
panic!("impl method FnLikeNode that is not fn-like")
}
map::NodeExpr(e) => match e.node {
ast::ExprClosure(_, ref decl, ref block) =>
- closure(ClosureParts::new(&decl, &block, e.id, e.span)),
+ closure(ClosureParts::new(&decl,
+ &block,
+ e.id,
+ e.span,
+ e.attrs.as_attr_slice())),
_ => panic!("expr FnLikeNode that is not fn-like"),
},
_ => panic!("other FnLikeNode that is not fn-like"),
sp: Span,
fn_id: NodeId) {
match kind {
- FnKind::Closure => {}
+ FnKind::Closure(_) => {}
_ => cx.param_env = ParameterEnvironment::for_item(cx.tcx, fn_id),
}
};
match fn_like.kind() {
- FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _) => {
+ FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _, _) => {
Some(fn_like)
}
- FnKind::Method(_, m, _) => {
+ FnKind::Method(_, m, _, _) => {
if m.constness == hir::Constness::Const {
Some(fn_like)
} else {
block: &'v hir::Block, span: Span, _: ast::NodeId) {
let (is_item_fn, is_unsafe_fn) = match fn_kind {
- FnKind::ItemFn(_, _, unsafety, _, _, _) =>
+ FnKind::ItemFn(_, _, unsafety, _, _, _, _) =>
(true, unsafety == hir::Unsafety::Unsafe),
- FnKind::Method(_, sig, _) =>
+ FnKind::Method(_, sig, _, _) =>
(true, sig.unsafety == hir::Unsafety::Unsafe),
_ => (false, false),
};
intravisit::walk_fn(self, fk, fd, b, s);
self.param_envs.pop();
}
- FnKind::Closure => {
+ FnKind::Closure(..) => {
intravisit::walk_fn(self, fk, fd, b, s);
}
}
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
b: &'v hir::Block, s: Span, fn_id: ast::NodeId) {
match fk {
- FnKind::ItemFn(_, generics, _, _, _, _) => {
+ FnKind::ItemFn(_, generics, _, _, _, _, _) => {
self.visit_early_late(subst::FnSpace, generics, |this| {
this.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
})
}
- FnKind::Method(_, sig, _) => {
+ FnKind::Method(_, sig, _, _) => {
self.visit_early_late(subst::FnSpace, &sig.generics, |this| {
this.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
})
}
- FnKind::Closure => {
+ FnKind::Closure(_) => {
self.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
}
}
fn_id: ast::NodeId) {
match fk {
- FnKind::ItemFn(_, generics, _, _, _, _) => {
+ FnKind::ItemFn(_, generics, _, _, _, _, _) => {
intravisit::walk_fn_decl(self, fd);
self.visit_generics(generics);
}
- FnKind::Method(_, sig, _) => {
+ FnKind::Method(_, sig, _, _) => {
intravisit::walk_fn_decl(self, fd);
self.visit_generics(&sig.generics);
self.visit_explicit_self(&sig.explicit_self);
}
- FnKind::Closure => {
+ FnKind::Closure(_) => {
intravisit::walk_fn_decl(self, fd);
}
}
self.free_region_map = old_free_region_map;
}
- FnKind::Closure => {
+ FnKind::Closure(..) => {
borrowck_fn(self, fk, fd, b, s, id);
}
}
use syntax::abi::Abi;
use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
+use syntax::attr::ThinAttributesExt;
use syntax::codemap::Span;
use hir::*;
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum FnKind<'a> {
/// fn foo() or extern "Abi" fn foo()
- ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, Visibility),
+ ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, Visibility, &'a [Attribute]),
/// fn foo(&self)
- Method(Name, &'a MethodSig, Option<Visibility>),
+ Method(Name, &'a MethodSig, Option<Visibility>, &'a [Attribute]),
/// |x, y| {}
- Closure,
+ Closure(&'a [Attribute]),
+}
+
+impl<'a> FnKind<'a> {
+ pub fn attrs(&self) -> &'a [Attribute] {
+ match *self {
+ FnKind::ItemFn(_, _, _, _, _, _, attrs) => attrs,
+ FnKind::Method(_, _, _, attrs) => attrs,
+ FnKind::Closure(attrs) => attrs,
+ }
+ }
}
/// Each method of the Visitor trait is a hook to be potentially
unsafety,
constness,
abi,
- item.vis),
+ item.vis,
+ &item.attrs),
declaration,
body,
item.span,
pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) {
match function_kind {
- FnKind::ItemFn(_, generics, _, _, _, _) => {
+ FnKind::ItemFn(_, generics, _, _, _, _, _) => {
visitor.visit_generics(generics);
}
- FnKind::Method(_, sig, _) => {
+ FnKind::Method(_, sig, _, _) => {
visitor.visit_generics(&sig.generics);
visitor.visit_explicit_self(&sig.explicit_self);
}
- FnKind::Closure => {}
+ FnKind::Closure(_) => {}
}
}
walk_fn_decl(visitor, &sig.decl);
}
MethodTraitItem(ref sig, Some(ref body)) => {
- visitor.visit_fn(FnKind::Method(trait_item.name, sig, None),
+ visitor.visit_fn(FnKind::Method(trait_item.name,
+ sig,
+ None,
+ &trait_item.attrs),
&sig.decl,
body,
trait_item.span,
visitor.visit_expr(expr);
}
ImplItemKind::Method(ref sig, ref body) => {
- visitor.visit_fn(FnKind::Method(impl_item.name, sig, Some(impl_item.vis)),
+ visitor.visit_fn(FnKind::Method(impl_item.name,
+ sig,
+ Some(impl_item.vis),
+ &impl_item.attrs),
&sig.decl,
body,
impl_item.span,
walk_list!(visitor, visit_arm, arms);
}
ExprClosure(_, ref function_declaration, ref body) => {
- visitor.visit_fn(FnKind::Closure,
+ visitor.visit_fn(FnKind::Closure(expression.attrs.as_attr_slice()),
function_declaration,
body,
expression.span,
self.operation.visit_id(node_id);
match function_kind {
- FnKind::ItemFn(_, generics, _, _, _, _) => {
+ FnKind::ItemFn(_, generics, _, _, _, _, _) => {
self.visit_generics_helper(generics)
}
- FnKind::Method(_, sig, _) => {
+ FnKind::Method(_, sig, _, _) => {
self.visit_generics_helper(&sig.generics)
}
- FnKind::Closure => {}
+ FnKind::Closure(_) => {}
}
for argument in &function_declaration.inputs {
fk: FnKind, _: &hir::FnDecl,
_: &hir::Block, span: Span, id: ast::NodeId) {
match fk {
- FnKind::Method(name, _, _) => match method_context(cx, id, span) {
+ FnKind::Method(name, _, _, _) => match method_context(cx, id, span) {
MethodLateContext::PlainImpl => {
self.check_snake_case(cx, "method", &name.as_str(), Some(span))
},
},
_ => (),
},
- FnKind::ItemFn(name, _, _, _, _, _) => {
+ FnKind::ItemFn(name, _, _, _, _, _, _) => {
self.check_snake_case(cx, "function", &name.as_str(), Some(span))
},
- _ => (),
+ FnKind::Closure(_) => (),
}
}
fn check_fn(&mut self, cx: &LateContext, fk: FnKind, _: &hir::FnDecl,
_: &hir::Block, span: Span, _: ast::NodeId) {
match fk {
- FnKind::ItemFn(_, _, hir::Unsafety::Unsafe, _, _, _) =>
+ FnKind::ItemFn(_, _, hir::Unsafety::Unsafe, _, _, _, _) =>
cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function"),
- FnKind::Method(_, sig, _) => {
+ FnKind::Method(_, sig, _, _) => {
if sig.unsafety == hir::Unsafety::Unsafe {
cx.span_lint(UNSAFE_CODE, span, "implementation of an `unsafe` method")
}
cx.tcx.impl_or_trait_item(cx.tcx.map.local_def_id(id)).as_opt_method()
}
// closures can't recur, so they don't matter.
- FnKind::Closure => return
+ FnKind::Closure(_) => return
};
// Walk through this function (say `f`) looking to see if
body: &'tcx hir::Block,
span: Span,
id: ast::NodeId) {
- let implicit_arg_tys = if let intravisit::FnKind::Closure = fk {
+ let implicit_arg_tys = if let intravisit::FnKind::Closure(..) = fk {
vec![closure_self_ty(&self.tcx, id, body.id)]
} else {
vec![]
}
let mode = match fk {
- FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _) => {
+ FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _, _) => {
Mode::ConstFn
}
- FnKind::Method(_, m, _) => {
+ FnKind::Method(_, m, _, _) => {
if m.constness == hir::Constness::Const {
Mode::ConstFn
} else {
_: Span,
node_id: NodeId) {
let rib_kind = match function_kind {
- FnKind::ItemFn(_, generics, _, _, _, _) => {
+ FnKind::ItemFn(_, generics, _, _, _, _, _) => {
self.visit_generics(generics);
ItemRibKind
}
- FnKind::Method(_, sig, _) => {
+ FnKind::Method(_, sig, _, _) => {
self.visit_generics(&sig.generics);
self.visit_explicit_self(&sig.explicit_self);
MethodRibKind
}
- FnKind::Closure => ClosureRibKind(node_id),
+ FnKind::Closure(_) => ClosureRibKind(node_id),
};
self.resolve_function(rib_kind, declaration, block);
}