From 18da3c671b8147fb8d4e206d487f0ee4e4c3ba11 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 26 Dec 2017 16:47:32 +0900 Subject: [PATCH 1/2] Do not expand a derive invocation when derive is not allowed 1. Change the return type of `expand_invoc()` and its subroutines to `Option` from `Expansion`. 2. Return `None` when expanding a derive invocation if the item cannot have derive on it (in `expand_derive_invoc()`). --- src/libsyntax/ext/base.rs | 12 ++ src/libsyntax/ext/expand.rs | 170 ++++++++++-------- .../derive-on-trait-item-or-impl-item.rs | 23 +++ 3 files changed, 126 insertions(+), 79 deletions(-) create mode 100644 src/test/compile-fail/derive-on-trait-item-or-impl-item.rs diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index d53335f5be7fb..be71d6e038c85 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -96,6 +96,18 @@ impl Annotatable { _ => panic!("expected Item") } } + + pub fn derive_allowed(&self) -> bool { + match *self { + Annotatable::Item(ref item) => match item.node { + ast::ItemKind::Struct(..) | + ast::ItemKind::Enum(..) | + ast::ItemKind::Union(..) => true, + _ => false, + }, + _ => false, + } + } } // A more flexible ItemDecorator. diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 81baa0c3954ca..11988a8f89d70 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -136,8 +136,8 @@ expansions! { } impl ExpansionKind { - fn dummy(self, span: Span) -> Expansion { - self.make_from(DummyResult::any(span)).unwrap() + fn dummy(self, span: Span) -> Option { + self.make_from(DummyResult::any(span)) } fn expect_from_annotatables>(self, items: I) -> Expansion { @@ -304,21 +304,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // FIXME(jseyfried): Refactor out the following logic let (expansion, new_invocations) = if let Some(ext) = ext { if let Some(ext) = ext { - let expansion = self.expand_invoc(invoc, ext); + let dummy = invoc.expansion_kind.dummy(invoc.span()).unwrap(); + let expansion = self.expand_invoc(invoc, ext).unwrap_or(dummy); self.collect_invocations(expansion, &[]) } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind { - let derive_allowed = match item { - Annotatable::Item(ref item) => match item.node { - ast::ItemKind::Struct(..) | - ast::ItemKind::Enum(..) | - ast::ItemKind::Union(..) => true, - _ => false, - }, - _ => false, - }; - if !derive_allowed { - let attr = item.attrs().iter() - .find(|attr| attr.check_name("derive")) + if !item.derive_allowed() { + let attr = attr::find_by_name(item.attrs(), "derive") .expect("`derive` attribute should exist"); let span = attr.span; let mut err = self.cx.mut_span_err(span, @@ -366,7 +357,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { unreachable!() } } else { - self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()), &[]) + self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()).unwrap(), &[]) }; if expansions.len() < depth { @@ -446,11 +437,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } - fn expand_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { + fn expand_invoc(&mut self, invoc: Invocation, ext: Rc) -> Option { let result = match invoc.kind { - InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext), - InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext), - InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext), + InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?, + InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?, + InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext)?, }; if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { @@ -467,13 +458,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> { panic!(FatalError); } - result + Some(result) } - fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { + fn expand_attr_invoc(&mut self, + invoc: Invocation, + ext: Rc) + -> Option { let Invocation { expansion_kind: kind, .. } = invoc; let (attr, item) = match invoc.kind { - InvocationKind::Attr { attr, item, .. } => (attr.unwrap(), item), + InvocationKind::Attr { attr, item, .. } => (attr?, item), _ => unreachable!(), }; @@ -490,16 +484,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> { match *ext { MultiModifier(ref mac) => { - let meta = panictry!(attr.parse_meta(self.cx.parse_sess)); + let meta = attr.parse_meta(self.cx.parse_sess).ok()?; let item = mac.expand(self.cx, attr.span, &meta, item); - kind.expect_from_annotatables(item) + Some(kind.expect_from_annotatables(item)) } MultiDecorator(ref mac) => { let mut items = Vec::new(); - let meta = panictry!(attr.parse_meta(self.cx.parse_sess)); + let meta = attr.parse_meta(self.cx.parse_sess).ok()?; mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item)); items.push(item); - kind.expect_from_annotatables(items) + Some(kind.expect_from_annotatables(items)) } AttrProcMacro(ref mac) => { let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item { @@ -525,7 +519,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } /// Expand a macro invocation. Returns the result of expansion. - fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { + fn expand_bang_invoc(&mut self, + invoc: Invocation, + ext: Rc) + -> Option { let (mark, kind) = (invoc.expansion_data.mark, invoc.expansion_kind); let (mac, ident, span) = match invoc.kind { InvocationKind::Bang { mac, ident, span } => (mac, ident, span), @@ -558,9 +555,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { false, false) { self.cx.span_err(path.span, &msg); self.cx.trace_macros_diag(); - return kind.dummy(span); + kind.dummy(span) + } else { + kind.make_from(expand.expand(self.cx, span, mac.node.stream())) } - kind.make_from(expand.expand(self.cx, span, mac.node.stream())) } NormalTT { @@ -574,9 +572,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { allow_internal_unsafe) { self.cx.span_err(path.span, &msg); self.cx.trace_macros_diag(); - return kind.dummy(span); + kind.dummy(span) + } else { + kind.make_from(expander.expand(self.cx, span, mac.node.stream())) } - kind.make_from(expander.expand(self.cx, span, mac.node.stream())) } IdentTT(ref expander, tt_span, allow_internal_unstable) => { @@ -584,34 +583,34 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.span_err(path.span, &format!("macro {}! expects an ident argument", path)); self.cx.trace_macros_diag(); - return kind.dummy(span); - }; - - invoc.expansion_data.mark.set_expn_info(ExpnInfo { - call_site: span, - callee: NameAndSpan { - format: macro_bang_format(path), - span: tt_span, - allow_internal_unstable, - allow_internal_unsafe: false, - } - }); + kind.dummy(span) + } else { + invoc.expansion_data.mark.set_expn_info(ExpnInfo { + call_site: span, + callee: NameAndSpan { + format: macro_bang_format(path), + span: tt_span, + allow_internal_unstable, + allow_internal_unsafe: false, + } + }); - let input: Vec<_> = mac.node.stream().into_trees().collect(); - kind.make_from(expander.expand(self.cx, span, ident, input)) + let input: Vec<_> = mac.node.stream().into_trees().collect(); + kind.make_from(expander.expand(self.cx, span, ident, input)) + } } MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => { self.cx.span_err(path.span, &format!("`{}` can only be used in attributes", path)); self.cx.trace_macros_diag(); - return kind.dummy(span); + kind.dummy(span) } ProcMacroDerive(..) | BuiltinDerive(..) => { self.cx.span_err(path.span, &format!("`{}` is a derive mode", path)); self.cx.trace_macros_diag(); - return kind.dummy(span); + kind.dummy(span) } ProcMacro(ref expandfun) => { @@ -620,43 +619,51 @@ impl<'a, 'b> MacroExpander<'a, 'b> { format!("macro {}! expects no ident argument, given '{}'", path, ident); self.cx.span_err(path.span, &msg); self.cx.trace_macros_diag(); - return kind.dummy(span); - } + kind.dummy(span) + } else { + invoc.expansion_data.mark.set_expn_info(ExpnInfo { + call_site: span, + callee: NameAndSpan { + format: macro_bang_format(path), + // FIXME procedural macros do not have proper span info + // yet, when they do, we should use it here. + span: None, + // FIXME probably want to follow macro_rules macros here. + allow_internal_unstable: false, + allow_internal_unsafe: false, + }, + }); - invoc.expansion_data.mark.set_expn_info(ExpnInfo { - call_site: span, - callee: NameAndSpan { - format: macro_bang_format(path), - // FIXME procedural macros do not have proper span info - // yet, when they do, we should use it here. - span: None, - // FIXME probably want to follow macro_rules macros here. - allow_internal_unstable: false, - allow_internal_unsafe: false, - }, - }); - - let tok_result = expandfun.expand(self.cx, span, mac.node.stream()); - Some(self.parse_expansion(tok_result, kind, path, span)) + let tok_result = expandfun.expand(self.cx, span, mac.node.stream()); + self.parse_expansion(tok_result, kind, path, span) + } } }; - unwrap_or!(opt_expanded, { + if opt_expanded.is_some() { + opt_expanded + } else { let msg = format!("non-{kind} macro in {kind} position: {name}", name = path.segments[0].identifier.name, kind = kind.name()); self.cx.span_err(path.span, &msg); self.cx.trace_macros_diag(); kind.dummy(span) - }) + } } /// Expand a derive invocation. Returns the result of expansion. - fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { + fn expand_derive_invoc(&mut self, + invoc: Invocation, + ext: Rc) + -> Option { let Invocation { expansion_kind: kind, .. } = invoc; let (path, item) = match invoc.kind { InvocationKind::Derive { path, item } => (path, item), _ => unreachable!(), }; + if !item.derive_allowed() { + return None; + } let pretty_name = Symbol::intern(&format!("derive({})", path)); let span = path.span; @@ -686,15 +693,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> { span: DUMMY_SP, node: ast::MetaItemKind::Word, }; - kind.expect_from_annotatables(ext.expand(self.cx, span, &dummy, item)) + Some(kind.expect_from_annotatables(ext.expand(self.cx, span, &dummy, item))) } BuiltinDerive(func) => { expn_info.callee.allow_internal_unstable = true; invoc.expansion_data.mark.set_expn_info(expn_info); let span = span.with_ctxt(self.cx.backtrace()); let mut items = Vec::new(); - func(self.cx, span, &attr.meta().unwrap(), &item, &mut |a| items.push(a)); - kind.expect_from_annotatables(items) + func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a)); + Some(kind.expect_from_annotatables(items)) } _ => { let msg = &format!("macro `{}` may not be used for derive attributes", attr.path); @@ -705,19 +712,24 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } - fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, path: &Path, span: Span) - -> Expansion { + fn parse_expansion(&mut self, + toks: TokenStream, + kind: ExpansionKind, + path: &Path, + span: Span) + -> Option { let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::>()); - let expansion = match parser.parse_expansion(kind, false) { - Ok(expansion) => expansion, + match parser.parse_expansion(kind, false) { + Ok(expansion) => { + parser.ensure_complete_parse(path, kind.name(), span); + Some(expansion) + } Err(mut err) => { err.emit(); self.cx.trace_macros_diag(); - return kind.dummy(span); + kind.dummy(span) } - }; - parser.ensure_complete_parse(path, kind.name(), span); - expansion + } } } diff --git a/src/test/compile-fail/derive-on-trait-item-or-impl-item.rs b/src/test/compile-fail/derive-on-trait-item-or-impl-item.rs new file mode 100644 index 0000000000000..9ff1c14f54c6e --- /dev/null +++ b/src/test/compile-fail/derive-on-trait-item-or-impl-item.rs @@ -0,0 +1,23 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + #[derive(Clone)] + //~^ ERROR `derive` may only be applied to structs, enums and unions + type Bar; +} + +impl Bar { + #[derive(Clone)] + //~^ ERROR `derive` may only be applied to structs, enums and unions + fn bar(&self) {} +} + +fn main() {} From f4a76f36afee62c36e67d84734a4bf94ff871355 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 26 Dec 2017 16:52:27 +0900 Subject: [PATCH 2/2] Prefer to use attr::contains_name() and attr::find_by_name() --- src/librustc/hir/lowering.rs | 6 +++--- src/librustc/traits/on_unimplemented.rs | 4 +--- src/librustc/ty/mod.rs | 2 +- src/librustc_driver/README.md | 2 +- src/librustc_lint/bad_style.rs | 4 +--- src/librustc_mir/hair/cx/mod.rs | 4 ++-- src/librustc_passes/ast_validation.rs | 5 ++--- src/librustc_resolve/build_reduced_graph.rs | 3 +-- src/librustc_trans_utils/link.rs | 6 +++--- src/libsyntax/test.rs | 6 +++--- src/libsyntax_ext/proc_macro_registrar.rs | 4 ++-- .../auxiliary/custom_derive_plugin_attr.rs | 3 ++- .../proc-macro/auxiliary/issue-40001-plugin.rs | 3 ++- 13 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 6fc35e5302dbb..e435f14470c57 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1571,7 +1571,7 @@ impl<'a> LoweringContext<'a> { bounds, default: tp.default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)), span: tp.span, - pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")), + pure_wrt_drop: attr::contains_name(&tp.attrs, "may_dangle"), synthetic: tp.attrs.iter() .filter(|attr| attr.check_name("rustc_synthetic")) .map(|_| hir::SyntheticTyParamKind::ImplTrait) @@ -1611,7 +1611,7 @@ impl<'a> LoweringContext<'a> { let def = hir::LifetimeDef { lifetime: self.lower_lifetime(&l.lifetime), bounds: self.lower_lifetimes(&l.bounds), - pure_wrt_drop: l.attrs.iter().any(|attr| attr.check_name("may_dangle")), + pure_wrt_drop: attr::contains_name(&l.attrs, "may_dangle"), in_band: false, }; @@ -2331,7 +2331,7 @@ impl<'a> LoweringContext<'a> { let mut vis = self.lower_visibility(&i.vis, None); let attrs = self.lower_attrs(&i.attrs); if let ItemKind::MacroDef(ref def) = i.node { - if !def.legacy || i.attrs.iter().any(|attr| attr.path == "macro_export") { + if !def.legacy || attr::contains_name(&i.attrs, "macro_export") { let body = self.lower_token_stream(def.stream()); self.exported_macros.push(hir::MacroDef { name, diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 16e200d56f9fb..757b078086d9c 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -140,9 +140,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { { let attrs = tcx.get_attrs(impl_def_id); - let attr = if let Some(item) = - attrs.into_iter().find(|a| a.check_name("rustc_on_unimplemented")) - { + let attr = if let Some(item) = attr::find_by_name(&attrs, "rustc_on_unimplemented") { item } else { return Ok(None); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 329dc6b502598..12e5451f83cf4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2402,7 +2402,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Determine whether an item is annotated with an attribute pub fn has_attr(self, did: DefId, attr: &str) -> bool { - self.get_attrs(did).iter().any(|item| item.check_name(attr)) + attr::contains_name(&self.get_attrs(did), attr) } /// Returns true if this is an `auto trait`. diff --git a/src/librustc_driver/README.md b/src/librustc_driver/README.md index 5331a05b5cd8e..839d1831f9544 100644 --- a/src/librustc_driver/README.md +++ b/src/librustc_driver/README.md @@ -3,7 +3,7 @@ compiler as a whole, see [the README.md file found in `librustc`](../librustc/README.md). The `driver` crate is effectively the "main" function for the rust -compiler. It orchstrates the compilation process and "knits together" +compiler. It orchestrates the compilation process and "knits together" the code from the other crates within rustc. This crate itself does not contain any of the "main logic" of the compiler (though it does have some code related to pretty printing or other minor compiler diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 49f14e8484f3a..0303b503691d1 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -221,9 +221,7 @@ impl LintPass for NonSnakeCase { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) { - let attr_crate_name = cr.attrs - .iter() - .find(|at| at.check_name("crate_name")) + let attr_crate_name = attr::find_by_name(&cr.attrs, "crate_name") .and_then(|at| at.value_str().map(|s| (at, s))); if let Some(ref name) = cx.tcx.sess.opts.crate_name { self.check_snake_case(cx, "crate", name, None); diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 306b41714a553..725a1b845e7ea 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -27,6 +27,7 @@ use rustc::ty::subst::Subst; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; use syntax::ast; +use syntax::attr; use syntax::symbol::Symbol; use rustc::hir; use rustc_const_math::{ConstInt, ConstUsize}; @@ -78,8 +79,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { // Some functions always have overflow checks enabled, // however, they may not get codegen'd, depending on // the settings for the crate they are translated in. - let mut check_overflow = attrs.iter() - .any(|item| item.check_name("rustc_inherit_overflow_checks")); + let mut check_overflow = attr::contains_name(attrs, "rustc_inherit_overflow_checks"); // Respect -C overflow-checks. check_overflow |= tcx.sess.overflow_checks(); diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index d74a8af921bea..61f54774163d4 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -51,8 +51,7 @@ impl<'a> AstValidator<'a> { } fn invalid_non_exhaustive_attribute(&self, variant: &Variant) { - let has_non_exhaustive = variant.node.attrs.iter() - .any(|attr| attr.check_name("non_exhaustive")); + let has_non_exhaustive = attr::contains_name(&variant.node.attrs, "non_exhaustive"); if has_non_exhaustive { self.err_handler().span_err(variant.span, "#[non_exhaustive] is not yet supported on variants"); @@ -308,7 +307,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ItemKind::Mod(_) => { // Ensure that `path` attributes on modules are recorded as used (c.f. #35584). attr::first_attr_value_str_by_name(&item.attrs, "path"); - if item.attrs.iter().any(|attr| attr.check_name("warn_directory_ownership")) { + if attr::contains_name(&item.attrs, "warn_directory_ownership") { let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP; let msg = "cannot declare a new module at this location"; self.session.buffer_lint(lint, item.id, item.span, msg); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 72017ec215f82..5866c8f93f094 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -358,8 +358,7 @@ impl<'a> Resolver<'a> { let mut ctor_vis = vis; - let has_non_exhaustive = item.attrs.iter() - .any(|item| item.check_name("non_exhaustive")); + let has_non_exhaustive = attr::contains_name(&item.attrs, "non_exhaustive"); // If the structure is marked as non_exhaustive then lower the visibility // to within the crate. diff --git a/src/librustc_trans_utils/link.rs b/src/librustc_trans_utils/link.rs index 643494e411d23..aabe931d79c57 100644 --- a/src/librustc_trans_utils/link.rs +++ b/src/librustc_trans_utils/link.rs @@ -13,7 +13,7 @@ use rustc::session::Session; use rustc::middle::cstore::{self, LinkMeta}; use rustc::hir::svh::Svh; use std::path::{Path, PathBuf}; -use syntax::ast; +use syntax::{ast, attr}; use syntax_pos::Span; pub fn out_filename(sess: &Session, @@ -69,8 +69,8 @@ pub fn find_crate_name(sess: Option<&Session>, // as used. After doing this, however, we still prioritize a crate name from // the command line over one found in the #[crate_name] attribute. If we // find both we ensure that they're the same later on as well. - let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name")) - .and_then(|at| at.value_str().map(|s| (at, s))); + let attr_crate_name = attr::find_by_name(attrs, "crate_name") + .and_then(|at| at.value_str().map(|s| (at, s))); if let Some(sess) = sess { if let Some(ref s) = sess.opts.crate_name { diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 1a0f4e9278da6..eff7dd57f08af 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -386,15 +386,15 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { } fn is_ignored(i: &ast::Item) -> bool { - i.attrs.iter().any(|attr| attr.check_name("ignore")) + attr::contains_name(&i.attrs, "ignore") } fn is_allowed_fail(i: &ast::Item) -> bool { - i.attrs.iter().any(|attr| attr.check_name("allow_fail")) + attr::contains_name(&i.attrs, "allow_fail") } fn should_panic(i: &ast::Item, cx: &TestCtxt) -> ShouldPanic { - match i.attrs.iter().find(|attr| attr.check_name("should_panic")) { + match attr::find_by_name(&i.attrs, "should_panic") { Some(attr) => { let sd = cx.span_diagnostic; if attr.is_value_str() { diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index a58d2c96388ca..8c5276e1d74b5 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -13,6 +13,7 @@ use std::mem; use errors; use syntax::ast::{self, Ident, NodeId}; +use syntax::attr; use syntax::codemap::{ExpnInfo, NameAndSpan, MacroAttribute}; use syntax::ext::base::ExtCtxt; use syntax::ext::build::AstBuilder; @@ -248,8 +249,7 @@ impl<'a> CollectProcMacros<'a> { impl<'a> Visitor<'a> for CollectProcMacros<'a> { fn visit_item(&mut self, item: &'a ast::Item) { if let ast::ItemKind::MacroDef(..) = item.node { - if self.is_proc_macro_crate && - item.attrs.iter().any(|attr| attr.path == "macro_export") { + if self.is_proc_macro_crate && attr::contains_name(&item.attrs, "macro_export") { let msg = "cannot export macro_rules! macros from a `proc-macro` crate type currently"; self.handler.span_err(item.span, msg); diff --git a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs index 1a9358f22bfce..0f90cb3752cf5 100644 --- a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs +++ b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs @@ -21,6 +21,7 @@ extern crate rustc; extern crate rustc_plugin; use syntax::ast; +use syntax::attr; use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable}; use syntax::ext::build::AstBuilder; use syntax::symbol::Symbol; @@ -80,7 +81,7 @@ fn totalsum_substructure(cx: &mut ExtCtxt, trait_span: Span, }; fields.iter().fold(cx.expr_isize(trait_span, 0), |acc, ref item| { - if item.attrs.iter().find(|a| a.check_name("ignore")).is_some() { + if attr::contains_name(&item.attrs, "ignore") { acc } else { cx.expr_binary(item.span, ast::BinOpKind::Add, acc, diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs index 29b6cc012b393..8502918813d71 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs @@ -17,6 +17,7 @@ extern crate rustc_plugin; extern crate syntax; use rustc_plugin::Registry; +use syntax::attr; use syntax::ext::base::*; use syntax::feature_gate::AttributeType::Whitelisted; use syntax::symbol::Symbol; @@ -59,7 +60,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass { _ => cx.tcx.hir.expect_item(cx.tcx.hir.get_parent(id)), }; - if !item.attrs.iter().any(|a| a.check_name("whitelisted_attr")) { + if attr::contains_name(&item.attrs, "whitelisted_attr") { cx.span_lint(MISSING_WHITELISTED_ATTR, span, "Missing 'whitelited_attr' attribute"); }