From 4b413bc393d8cde89ce0d687c3ef4ea50374af2c Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 2 Feb 2017 00:33:42 +0000 Subject: [PATCH 1/2] Move legacy custom derives collection into `resolver.find_attr_invoc()`. --- src/librustc_resolve/macros.rs | 57 ++++++++++++++++++++++++++++++++-- src/libsyntax/ext/derive.rs | 36 +-------------------- 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index ea3112b2463f..a1699784b9db 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -27,10 +27,10 @@ use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension}; use syntax::ext::expand::{Expansion, mark_tts}; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; -use syntax::feature_gate::{emit_feature_err, GateIssue, is_builtin_attr}; +use syntax::feature_gate::{self, emit_feature_err, GateIssue, is_builtin_attr}; use syntax::fold::{self, Folder}; use syntax::ptr::P; -use syntax::symbol::keywords; +use syntax::symbol::{Symbol, keywords}; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::Visitor; use syntax_pos::{Span, DUMMY_SP}; @@ -188,6 +188,49 @@ impl<'a> base::Resolver for Resolver<'a> { return Some(attrs.remove(i)); } } + + // Check for legacy derives + for i in 0..attrs.len() { + if attrs[i].name() == "derive" { + let mut traits = match attrs[i].meta_item_list() { + Some(traits) if !traits.is_empty() => traits.to_owned(), + _ => continue, + }; + + for j in 0..traits.len() { + let legacy_name = Symbol::intern(&match traits[j].word() { + Some(..) => format!("derive_{}", traits[j].name().unwrap()), + None => continue, + }); + if !self.builtin_macros.contains_key(&legacy_name) { + continue + } + let span = traits.remove(j).span; + self.gate_legacy_custom_derive(legacy_name, span); + if traits.is_empty() { + attrs.remove(i); + } else { + attrs[i].value = ast::MetaItem { + name: attrs[i].name(), + span: span, + node: ast::MetaItemKind::List(traits), + }; + } + return Some(ast::Attribute { + value: ast::MetaItem { + name: legacy_name, + span: span, + node: ast::MetaItemKind::Word, + }, + id: attr::mk_attr_id(), + style: ast::AttrStyle::Outer, + is_sugared_doc: false, + span: span, + }); + } + } + } + None } @@ -540,4 +583,14 @@ impl<'a> Resolver<'a> { `use {}::{};`", crate_name, name)) .emit(); } + + fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) { + if !self.session.features.borrow().custom_derive { + let sess = &self.session.parse_sess; + let explain = feature_gate::EXPLAIN_CUSTOM_DERIVE; + emit_feature_err(sess, "custom_derive", span, GateIssue::Language, explain); + } else if !self.is_whitelisted_legacy_custom_derive(name) { + self.session.span_warn(span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE); + } + } } diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 946448eaaee9..ba14a153ed29 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -13,7 +13,6 @@ use attr; use ast::{self, NestedMetaItem}; use ext::base::{ExtCtxt, SyntaxExtension}; use codemap; use ext::build::AstBuilder; -use feature_gate; use symbol::Symbol; use syntax_pos::Span; @@ -64,7 +63,6 @@ pub fn verify_derive_attrs(cx: &mut ExtCtxt, attrs: &[ast::Attribute]) { #[derive(PartialEq, Debug, Clone, Copy)] pub enum DeriveType { - Legacy, ProcMacro, Builtin } @@ -72,12 +70,6 @@ pub enum DeriveType { impl DeriveType { // Classify a derive trait name by resolving the macro. pub fn classify(cx: &mut ExtCtxt, tname: Name) -> DeriveType { - let legacy_derive_name = Symbol::intern(&format!("derive_{}", tname)); - - if let Ok(_) = cx.resolver.resolve_builtin_macro(legacy_derive_name) { - return DeriveType::Legacy; - } - match cx.resolver.resolve_builtin_macro(tname) { Ok(ext) => match *ext { SyntaxExtension::BuiltinDerive(..) => DeriveType::Builtin, @@ -185,33 +177,7 @@ pub fn add_derived_markers(cx: &mut ExtCtxt, attrs: &mut Vec) { pub fn find_derive_attr(cx: &mut ExtCtxt, attrs: &mut Vec) -> Option { verify_derive_attrs(cx, attrs); - get_derive_attr(cx, attrs, DeriveType::Legacy).and_then(|a| { - let titem = derive_attr_trait(cx, &a); - titem.and_then(|titem| { - let tword = titem.word().unwrap(); - let tname = tword.name(); - if !cx.ecfg.enable_custom_derive() { - feature_gate::emit_feature_err( - &cx.parse_sess, - "custom_derive", - titem.span, - feature_gate::GateIssue::Language, - feature_gate::EXPLAIN_CUSTOM_DERIVE - ); - None - } else { - let name = Symbol::intern(&format!("derive_{}", tname)); - if !cx.resolver.is_whitelisted_legacy_custom_derive(name) { - cx.span_warn(titem.span, - feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE); - } - let mitem = cx.meta_word(titem.span, name); - Some(cx.attribute(mitem.span, mitem)) - } - }) - }).or_else(|| { - get_derive_attr(cx, attrs, DeriveType::ProcMacro) - }).or_else(|| { + get_derive_attr(cx, attrs, DeriveType::ProcMacro).or_else(|| { add_derived_markers(cx, attrs); get_derive_attr(cx, attrs, DeriveType::Builtin) }) From 2cc61eebb7f1677af2a20f76fb1411ed40f6901b Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 2 Feb 2017 07:01:15 +0000 Subject: [PATCH 2/2] Allow using inert attributes from `proc_macro_derive`s with `#![feature(proc_macro)]`. --- src/librustc_metadata/creader.rs | 7 +- src/librustc_resolve/macros.rs | 27 +- src/libsyntax/ext/base.rs | 15 +- src/libsyntax/ext/derive.rs | 170 +++--------- src/libsyntax/ext/expand.rs | 261 ++++++++++++------ src/libsyntax/ext/placeholders.rs | 13 +- src/libsyntax_ext/deriving/custom.rs | 8 +- src/test/compile-fail-fulldeps/gated-quote.rs | 28 +- .../macro-crate-unexported-macro.rs | 2 +- .../feature-gate-rustc-diagnostic-macros.rs | 6 +- src/test/compile-fail/issue-11692.rs | 4 +- src/test/compile-fail/issue-19734.rs | 2 +- src/test/compile-fail/macro-error.rs | 2 +- src/test/compile-fail/macro_undefined.rs | 4 +- src/test/compile-fail/self_type_keyword.rs | 2 +- .../proc-macro/auxiliary/derive-a.rs | 1 - .../proc-macro/auxiliary/derive-atob.rs | 2 +- .../proc-macro/auxiliary/derive-b.rs | 1 - 18 files changed, 274 insertions(+), 281 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 55dc5aa2876f..104d76b1f600 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -616,10 +616,9 @@ impl<'a> CrateLoader<'a> { trait_name: &str, expand: fn(TokenStream) -> TokenStream, attributes: &[&'static str]) { - let attrs = attributes.iter().cloned().map(Symbol::intern).collect(); - let derive = SyntaxExtension::ProcMacroDerive( - Box::new(ProcMacroDerive::new(expand, attrs)) - ); + let attrs = attributes.iter().cloned().map(Symbol::intern).collect::>(); + let derive = ProcMacroDerive::new(expand, attrs.clone()); + let derive = SyntaxExtension::ProcMacroDerive(Box::new(derive), attrs); self.0.push((Symbol::intern(trait_name), Rc::new(derive))); } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index a1699784b9db..97d3e6c9e43d 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -27,7 +27,7 @@ use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension}; use syntax::ext::expand::{Expansion, mark_tts}; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; -use syntax::feature_gate::{self, emit_feature_err, GateIssue, is_builtin_attr}; +use syntax::feature_gate::{self, emit_feature_err, GateIssue}; use syntax::fold::{self, Folder}; use syntax::ptr::P; use syntax::symbol::{Symbol, keywords}; @@ -130,12 +130,16 @@ impl<'a> base::Resolver for Resolver<'a> { self.whitelisted_legacy_custom_derives.contains(&name) } - fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) { + fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]) { let invocation = self.invocations[&mark]; self.collect_def_ids(invocation, expansion); self.current_module = invocation.module.get(); self.current_module.unresolved_invocations.borrow_mut().remove(&mark); + self.current_module.unresolved_invocations.borrow_mut().extend(derives); + for &derive in derives { + self.invocations.insert(derive, invocation); + } let mut visitor = BuildReducedGraphVisitor { resolver: self, legacy_scope: LegacyScope::Invocation(invocation), @@ -172,7 +176,9 @@ impl<'a> base::Resolver for Resolver<'a> { ImportResolver { resolver: self }.resolve_imports() } - fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option { + // Resolves attribute and derive legacy macros from `#![plugin(..)]`. + fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec) + -> Option { for i in 0..attrs.len() { match self.builtin_macros.get(&attrs[i].name()).cloned() { Some(binding) => match *binding.get_macro(self) { @@ -183,10 +189,6 @@ impl<'a> base::Resolver for Resolver<'a> { }, None => {} } - - if self.proc_macro_enabled && !is_builtin_attr(&attrs[i]) { - return Some(attrs.remove(i)); - } } // Check for legacy derives @@ -212,7 +214,7 @@ impl<'a> base::Resolver for Resolver<'a> { } else { attrs[i].value = ast::MetaItem { name: attrs[i].name(), - span: span, + span: attrs[i].span, node: ast::MetaItemKind::List(traits), }; } @@ -279,7 +281,7 @@ impl<'a> base::Resolver for Resolver<'a> { Ok(binding) => Ok(binding.get_macro(self)), Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined), _ => { - let msg = format!("macro undefined: '{}!'", name); + let msg = format!("macro undefined: `{}`", name); let mut err = self.session.struct_span_err(span, &msg); self.suggest_macro_name(&name.as_str(), &mut err); err.emit(); @@ -294,13 +296,6 @@ impl<'a> base::Resolver for Resolver<'a> { result } - fn resolve_builtin_macro(&mut self, tname: Name) -> Result, Determinacy> { - match self.builtin_macros.get(&tname).cloned() { - Some(binding) => Ok(binding.get_macro(self)), - None => Err(Determinacy::Undetermined), - } - } - fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) -> Result, Determinacy> { let ast::Path { span, .. } = *path; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 9a717b86d091..b5afd0c453a1 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -514,7 +514,7 @@ pub enum SyntaxExtension { /// The input is the annotated item. /// Allows generating code to implement a Trait for a given struct /// or enum item. - ProcMacroDerive(Box), + ProcMacroDerive(Box, Vec /* inert attribute names */), /// An attribute-like procedural macro that derives a builtin trait. BuiltinDerive(BuiltinDeriveFn), @@ -528,15 +528,15 @@ pub trait Resolver { fn eliminate_crate_var(&mut self, item: P) -> P; fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool; - fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion); + fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]); fn add_ext(&mut self, ident: ast::Ident, ext: Rc); fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec); fn resolve_imports(&mut self); - fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option; + // Resolves attribute and derive legacy macros from `#![plugin(..)]`. + fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec) -> Option; fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) -> Result, Determinacy>; - fn resolve_builtin_macro(&mut self, tname: Name) -> Result, Determinacy>; fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) -> Result, Determinacy>; } @@ -555,19 +555,16 @@ impl Resolver for DummyResolver { fn eliminate_crate_var(&mut self, item: P) -> P { item } fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false } - fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {} + fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion, _derives: &[Mark]) {} fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc) {} fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec) {} fn resolve_imports(&mut self) {} - fn find_attr_invoc(&mut self, _attrs: &mut Vec) -> Option { None } + fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec) -> Option { None } fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool) -> Result, Determinacy> { Err(Determinacy::Determined) } - fn resolve_builtin_macro(&mut self, _tname: Name) -> Result, Determinacy> { - Err(Determinacy::Determined) - } fn resolve_derive_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool) -> Result, Determinacy> { Err(Determinacy::Determined) diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index ba14a153ed29..77cc7bab0315 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -8,124 +8,42 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::Name; -use attr; -use ast::{self, NestedMetaItem}; use ext::base::{ExtCtxt, SyntaxExtension}; -use codemap; +use attr::HasAttrs; +use {ast, codemap}; +use ext::base::ExtCtxt; use ext::build::AstBuilder; use symbol::Symbol; use syntax_pos::Span; -pub fn derive_attr_trait<'a>(cx: &mut ExtCtxt, attr: &'a ast::Attribute) - -> Option<&'a NestedMetaItem> { - if attr.name() != "derive" { - return None; - } - if attr.value_str().is_some() { - cx.span_err(attr.span, "unexpected value in `derive`"); - return None; - } - - let traits = attr.meta_item_list().unwrap_or(&[]); - - if traits.is_empty() { - cx.span_warn(attr.span, "empty trait list in `derive`"); - return None; - } - - return traits.get(0); -} - -pub fn verify_derive_attrs(cx: &mut ExtCtxt, attrs: &[ast::Attribute]) { - for attr in attrs { +pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec) -> Vec<(Symbol, Span)> { + let mut result = Vec::new(); + attrs.retain(|attr| { if attr.name() != "derive" { - continue; + return true; } if attr.value_str().is_some() { cx.span_err(attr.span, "unexpected value in `derive`"); + return false; } let traits = attr.meta_item_list().unwrap_or(&[]).to_owned(); - if traits.is_empty() { cx.span_warn(attr.span, "empty trait list in `derive`"); - attr::mark_used(&attr); - continue; + return false; } + for titem in traits { if titem.word().is_none() { cx.span_err(titem.span, "malformed `derive` entry"); + return false; } - } - } -} - -#[derive(PartialEq, Debug, Clone, Copy)] -pub enum DeriveType { - ProcMacro, - Builtin -} - -impl DeriveType { - // Classify a derive trait name by resolving the macro. - pub fn classify(cx: &mut ExtCtxt, tname: Name) -> DeriveType { - match cx.resolver.resolve_builtin_macro(tname) { - Ok(ext) => match *ext { - SyntaxExtension::BuiltinDerive(..) => DeriveType::Builtin, - _ => DeriveType::ProcMacro, - }, - Err(_) => DeriveType::ProcMacro, - } - } -} - -pub fn get_derive_attr(cx: &mut ExtCtxt, attrs: &mut Vec, - derive_type: DeriveType) -> Option { - for i in 0..attrs.len() { - if attrs[i].name() != "derive" { - continue; - } - - if attrs[i].value_str().is_some() { - continue; - } - - let mut traits = attrs[i].meta_item_list().unwrap_or(&[]).to_owned(); - - // First, weed out malformed #[derive] - traits.retain(|titem| titem.word().is_some()); - - let mut titem = None; - - // See if we can find a matching trait. - for j in 0..traits.len() { - let tname = match traits[j].name() { - Some(tname) => tname, - _ => continue, - }; - - if DeriveType::classify(cx, tname) == derive_type { - titem = Some(traits.remove(j)); - break; - } + result.push((titem.name().unwrap(), titem.span)); } - // If we find a trait, remove the trait from the attribute. - if let Some(titem) = titem { - if traits.len() == 0 { - attrs.remove(i); - } else { - let derive = Symbol::intern("derive"); - let mitem = cx.meta_list(titem.span, derive, traits); - attrs[i] = cx.attribute(titem.span, mitem); - } - let derive = Symbol::intern("derive"); - let mitem = cx.meta_list(titem.span, derive, vec![titem]); - return Some(cx.attribute(mitem.span, mitem)); - } - } - return None; + true + }); + result } fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span { @@ -142,43 +60,25 @@ fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span { } } -pub fn add_derived_markers(cx: &mut ExtCtxt, attrs: &mut Vec) { - if attrs.is_empty() { - return; - } - - let titems = attrs.iter().filter(|a| { - a.name() == "derive" - }).flat_map(|a| { - a.meta_item_list().unwrap_or(&[]).iter() - }).filter_map(|titem| { - titem.name() - }).collect::>(); - - let span = attrs[0].span; - - if !attrs.iter().any(|a| a.name() == "structural_match") && - titems.iter().any(|t| *t == "PartialEq") && titems.iter().any(|t| *t == "Eq") { - let structural_match = Symbol::intern("structural_match"); - let span = allow_unstable(cx, span, "derive(PartialEq, Eq)"); - let meta = cx.meta_word(span, structural_match); - attrs.push(cx.attribute(span, meta)); - } - - if !attrs.iter().any(|a| a.name() == "rustc_copy_clone_marker") && - titems.iter().any(|t| *t == "Copy") && titems.iter().any(|t| *t == "Clone") { - let structural_match = Symbol::intern("rustc_copy_clone_marker"); - let span = allow_unstable(cx, span, "derive(Copy, Clone)"); - let meta = cx.meta_word(span, structural_match); - attrs.push(cx.attribute(span, meta)); - } -} - -pub fn find_derive_attr(cx: &mut ExtCtxt, attrs: &mut Vec) - -> Option { - verify_derive_attrs(cx, attrs); - get_derive_attr(cx, attrs, DeriveType::ProcMacro).or_else(|| { - add_derived_markers(cx, attrs); - get_derive_attr(cx, attrs, DeriveType::Builtin) +pub fn add_derived_markers(cx: &mut ExtCtxt, traits: &[(Symbol, Span)], item: T) -> T { + let span = match traits.get(0) { + Some(&(_, span)) => span, + None => return item, + }; + + item.map_attrs(|mut attrs| { + if traits.iter().any(|&(name, _)| name == "PartialEq") && + traits.iter().any(|&(name, _)| name == "Eq") { + let span = allow_unstable(cx, span, "derive(PartialEq, Eq)"); + let meta = cx.meta_word(span, Symbol::intern("structural_match")); + attrs.push(cx.attribute(span, meta)); + } + if traits.iter().any(|&(name, _)| name == "Copy") && + traits.iter().any(|&(name, _)| name == "Clone") { + let span = allow_unstable(cx, span, "derive(Copy, Clone)"); + let meta = cx.meta_word(span, Symbol::intern("rustc_copy_clone_marker")); + attrs.push(cx.attribute(span, meta)); + } + attrs }) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 8e7f8830eafb..d011d7c2a1c4 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -14,10 +14,10 @@ use attr::{self, HasAttrs}; use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; use config::{is_test_or_bench, StripUnconfigured}; use ext::base::*; -use ext::derive::{find_derive_attr, derive_attr_trait}; +use ext::derive::{add_derived_markers, collect_derives}; use ext::hygiene::Mark; use ext::placeholders::{placeholder, PlaceholderExpander}; -use feature_gate::{self, Features}; +use feature_gate::{self, Features, is_builtin_attr}; use fold; use fold::*; use parse::parser::Parser; @@ -33,6 +33,7 @@ use tokenstream::{TokenTree, TokenStream}; use util::small_vector::SmallVector; use visit::Visitor; +use std::collections::HashMap; use std::mem; use std::path::PathBuf; use std::rc::Rc; @@ -164,11 +165,13 @@ pub enum InvocationKind { span: Span, }, Attr { - attr: ast::Attribute, + attr: Option, + traits: Vec<(Symbol, Span)>, item: Annotatable, }, Derive { - attr: ast::Attribute, + name: Symbol, + span: Span, item: Annotatable, }, } @@ -177,8 +180,9 @@ impl Invocation { fn span(&self) -> Span { match self.kind { InvocationKind::Bang { span, .. } => span, - InvocationKind::Attr { ref attr, .. } => attr.span, - InvocationKind::Derive { ref attr, .. } => attr.span, + InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span, + InvocationKind::Attr { attr: None, .. } => syntax_pos::DUMMY_SP, + InvocationKind::Derive { span, .. } => span, } } } @@ -227,15 +231,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let orig_expansion_data = self.cx.current_expansion.clone(); self.cx.current_expansion.depth = 0; - let (expansion, mut invocations) = self.collect_invocations(expansion); + let (expansion, mut invocations) = self.collect_invocations(expansion, &[]); self.resolve_imports(); invocations.reverse(); let mut expansions = Vec::new(); + let mut derives = HashMap::new(); let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { - let invoc = if let Some(invoc) = invocations.pop() { + let mut invoc = if let Some(invoc) = invocations.pop() { invoc } else { self.resolve_imports(); @@ -247,24 +252,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let scope = if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark }; - let resolution = match invoc.kind { - InvocationKind::Bang { ref mac, .. } => { - self.cx.resolver.resolve_macro(scope, &mac.node.path, force) - } - InvocationKind::Attr { ref attr, .. } => { - let ident = Ident::with_empty_ctxt(attr.name()); - let path = ast::Path::from_ident(attr.span, ident); - self.cx.resolver.resolve_macro(scope, &path, force) - } - InvocationKind::Derive { ref attr, .. } => { - let titem = derive_attr_trait(self.cx, &attr).unwrap(); - let tname = titem.name().expect("Expected derive macro name"); - let ident = Ident::with_empty_ctxt(tname); - let path = ast::Path::from_ident(attr.span, ident); - self.cx.resolver.resolve_derive_macro(scope, &path, force) - } - }; - let ext = match resolution { + let ext = match self.resolve_invoc(&mut invoc, scope, force) { Ok(ext) => Some(ext), Err(Determinacy::Determined) => None, Err(Determinacy::Undetermined) => { @@ -278,13 +266,49 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.current_expansion = invoc.expansion_data.clone(); self.cx.current_expansion.mark = scope; - let expansion = match ext { - Some(ext) => self.expand_invoc(invoc, ext), - None => invoc.expansion_kind.dummy(invoc.span()), + // 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); + self.collect_invocations(expansion, &[]) + } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind { + let item = item + .map_attrs(|mut attrs| { attrs.retain(|a| a.name() != "derive"); attrs }); + let item_with_markers = + add_derived_markers(&mut self.cx, &traits, item.clone()); + let derives = derives.entry(invoc.expansion_data.mark).or_insert_with(Vec::new); + + for &(name, span) in &traits { + let mark = Mark::fresh(); + derives.push(mark); + let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name)); + let item = match self.cx.resolver + .resolve_macro(Mark::root(), &path, false) { + Ok(ext) => match *ext { + SyntaxExtension::BuiltinDerive(..) => item_with_markers.clone(), + _ => item.clone(), + }, + _ => item.clone(), + }; + invocations.push(Invocation { + kind: InvocationKind::Derive { name: name, span: span, item: item }, + expansion_kind: invoc.expansion_kind, + expansion_data: ExpansionData { + mark: mark, + ..invoc.expansion_data.clone() + }, + }); + } + let expansion = invoc.expansion_kind + .expect_from_annotatables(::std::iter::once(item_with_markers)); + self.collect_invocations(expansion, derives) + } else { + unreachable!() + } + } else { + self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()), &[]) }; - let (expansion, new_invocations) = self.collect_invocations(expansion); - if expansions.len() < depth { expansions.push(Vec::new()); } @@ -299,7 +323,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); while let Some(expansions) = expansions.pop() { for (mark, expansion) in expansions.into_iter().rev() { - placeholder_expander.add(mark.as_placeholder_id(), expansion); + let derives = derives.remove(&mark).unwrap_or_else(Vec::new); + placeholder_expander.add(mark.as_placeholder_id(), expansion, derives); } } @@ -314,7 +339,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } - fn collect_invocations(&mut self, expansion: Expansion) -> (Expansion, Vec) { + fn collect_invocations(&mut self, expansion: Expansion, derives: &[Mark]) + -> (Expansion, Vec) { let result = { let mut collector = InvocationCollector { cfg: StripUnconfigured { @@ -332,13 +358,69 @@ impl<'a, 'b> MacroExpander<'a, 'b> { if self.monotonic { let err_count = self.cx.parse_sess.span_diagnostic.err_count(); let mark = self.cx.current_expansion.mark; - self.cx.resolver.visit_expansion(mark, &result.0); + self.cx.resolver.visit_expansion(mark, &result.0, derives); self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count; } result } + fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool) + -> Result>, Determinacy> { + let (attr, traits, item) = match invoc.kind { + InvocationKind::Bang { ref mac, .. } => { + return self.cx.resolver.resolve_macro(scope, &mac.node.path, force).map(Some); + } + InvocationKind::Attr { attr: None, .. } => return Ok(None), + InvocationKind::Derive { name, span, .. } => { + let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name)); + return self.cx.resolver.resolve_derive_macro(scope, &path, force).map(Some); + } + InvocationKind::Attr { ref mut attr, ref traits, ref mut item } => (attr, traits, item), + }; + + let (attr_name, path) = { + let attr = attr.as_ref().unwrap(); + (attr.name(), ast::Path::from_ident(attr.span, Ident::with_empty_ctxt(attr.name()))) + }; + + let mut determined = true; + match self.cx.resolver.resolve_macro(scope, &path, force) { + Ok(ext) => return Ok(Some(ext)), + Err(Determinacy::Undetermined) => determined = false, + Err(Determinacy::Determined) if force => return Err(Determinacy::Determined), + _ => {} + } + + for &(name, span) in traits { + let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name)); + match self.cx.resolver.resolve_macro(scope, &path, force) { + Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs) = *ext { + if inert_attrs.contains(&attr_name) { + // FIXME(jseyfried) Avoid `mem::replace` here. + let dummy_item = placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID) + .make_items().pop().unwrap(); + *item = mem::replace(item, Annotatable::Item(dummy_item)) + .map_attrs(|mut attrs| { + let inert_attr = attr.take().unwrap(); + attr::mark_known(&inert_attr); + if self.cx.ecfg.proc_macro_enabled() { + *attr = find_attr_invoc(&mut attrs); + } + attrs.push(inert_attr); + attrs + }); + } + return Err(Determinacy::Undetermined); + }, + Err(Determinacy::Undetermined) => determined = false, + Err(Determinacy::Determined) => {} + } + } + + Err(if determined { Determinacy::Determined } else { Determinacy::Undetermined }) + } + fn expand_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { match invoc.kind { InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext), @@ -350,7 +432,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { let Invocation { expansion_kind: kind, .. } = invoc; let (attr, item) = match invoc.kind { - InvocationKind::Attr { attr, item } => (attr, item), + InvocationKind::Attr { attr, item, .. } => (attr.unwrap(), item), _ => unreachable!(), }; @@ -503,64 +585,60 @@ impl<'a, 'b> MacroExpander<'a, 'b> { /// Expand a derive invocation. Returns the result of expansion. fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { let Invocation { expansion_kind: kind, .. } = invoc; - let (attr, item) = match invoc.kind { - InvocationKind::Derive { attr, item } => (attr, item), + let (name, span, item) = match invoc.kind { + InvocationKind::Derive { name, span, item } => (name, span, item), _ => unreachable!(), }; - attr::mark_used(&attr); - let titem = derive_attr_trait(self.cx, &attr).unwrap(); - let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap()); - let name = Symbol::intern(&format!("derive({})", tname)); - let mitem = &attr.value; + let mitem = ast::MetaItem { name: name, span: span, node: ast::MetaItemKind::Word }; + let pretty_name = Symbol::intern(&format!("derive({})", name)); self.cx.bt_push(ExpnInfo { - call_site: attr.span, + call_site: span, callee: NameAndSpan { - format: MacroAttribute(attr.name()), - span: Some(attr.span), + format: MacroAttribute(pretty_name), + span: Some(span), allow_internal_unstable: false, } }); match *ext { - SyntaxExtension::ProcMacroDerive(ref ext) => { + SyntaxExtension::ProcMacroDerive(ref ext, _) => { let span = Span { expn_id: self.cx.codemap().record_expansion(ExpnInfo { - call_site: mitem.span, + call_site: span, callee: NameAndSpan { - format: MacroAttribute(Symbol::intern(&format!("derive({})", tname))), + format: MacroAttribute(pretty_name), span: None, allow_internal_unstable: false, }, }), - ..mitem.span + ..span }; return kind.expect_from_annotatables(ext.expand(self.cx, span, &mitem, item)); } SyntaxExtension::BuiltinDerive(func) => { let span = Span { expn_id: self.cx.codemap().record_expansion(ExpnInfo { - call_site: titem.span, + call_site: span, callee: NameAndSpan { - format: MacroAttribute(name), + format: MacroAttribute(pretty_name), span: None, allow_internal_unstable: true, }, }), - ..titem.span + ..span }; let mut items = Vec::new(); func(self.cx, span, &mitem, &item, &mut |a| { items.push(a) }); - items.insert(0, item); return kind.expect_from_annotatables(items); } _ => { let msg = &format!("macro `{}` may not be used for derive attributes", name); - self.cx.span_err(attr.span, &msg); - kind.dummy(attr.span) + self.cx.span_err(span, &msg); + kind.dummy(span) } } } @@ -672,34 +750,40 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span }) } - fn collect_attr(&mut self, attr: ast::Attribute, item: Annotatable, kind: ExpansionKind) + fn collect_attr(&mut self, + attr: Option, + traits: Vec<(Symbol, Span)>, + item: Annotatable, + kind: ExpansionKind) -> Expansion { - let invoc_kind = if attr.name() == "derive" { - if kind == ExpansionKind::TraitItems || kind == ExpansionKind::ImplItems { - self.cx.span_err(attr.span, "`derive` can be only be applied to items"); - return kind.expect_from_annotatables(::std::iter::once(item)); - } - InvocationKind::Derive { attr: attr, item: item } - } else { - InvocationKind::Attr { attr: attr, item: item } - }; - - self.collect(kind, invoc_kind) + if !traits.is_empty() && + (kind == ExpansionKind::TraitItems || kind == ExpansionKind::ImplItems) { + self.cx.span_err(traits[0].1, "`derive` can be only be applied to items"); + return kind.expect_from_annotatables(::std::iter::once(item)); + } + self.collect(kind, InvocationKind::Attr { attr: attr, traits: traits, item: item }) } // If `item` is an attr invocation, remove and return the macro attribute. - fn classify_item(&mut self, mut item: T) -> (T, Option) { - let mut attr = None; + fn classify_item(&mut self, mut item: T) -> (Option, Vec<(Symbol, Span)>, T) + where T: HasAttrs, + { + let (mut attr, mut traits) = (None, Vec::new()); item = item.map_attrs(|mut attrs| { - attr = self.cx.resolver.find_attr_invoc(&mut attrs).or_else(|| { - find_derive_attr(self.cx, &mut attrs) - }); + if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs) { + attr = Some(legacy_attr_invoc); + return attrs; + } + if self.cx.ecfg.proc_macro_enabled() { + attr = find_attr_invoc(&mut attrs); + } + traits = collect_derives(&mut self.cx, &mut attrs); attrs }); - (item, attr) + (attr, traits, item) } fn configure(&mut self, node: T) -> Option { @@ -717,6 +801,16 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } } +fn find_attr_invoc(attrs: &mut Vec) -> Option { + for i in 0 .. attrs.len() { + if !attr::is_known(&attrs[i]) && !is_builtin_attr(&attrs[i]) { + return Some(attrs.remove(i)); + } + } + + None +} + // These are pretty nasty. Ideally, we would keep the tokens around, linked from // the AST. However, we don't so we need to create new ones. Since the item might // have come from a macro expansion (possibly only in part), we can't use the @@ -844,10 +938,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn fold_item(&mut self, item: P) -> SmallVector> { let item = configure!(self, item); - let (mut item, attr) = self.classify_item(item); - if let Some(attr) = attr { + let (attr, traits, mut item) = self.classify_item(item); + if attr.is_some() || !traits.is_empty() { let item = Annotatable::Item(fully_configure!(self, item, noop_fold_item)); - return self.collect_attr(attr, item, ExpansionKind::Items).make_items(); + return self.collect_attr(attr, traits, item, ExpansionKind::Items).make_items(); } match item.node { @@ -928,11 +1022,12 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector { let item = configure!(self, item); - let (item, attr) = self.classify_item(item); - if let Some(attr) = attr { + let (attr, traits, item) = self.classify_item(item); + if attr.is_some() || !traits.is_empty() { let item = Annotatable::TraitItem(P(fully_configure!(self, item, noop_fold_trait_item))); - return self.collect_attr(attr, item, ExpansionKind::TraitItems).make_trait_items() + return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems) + .make_trait_items() } match item.node { @@ -948,10 +1043,11 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVector { let item = configure!(self, item); - let (item, attr) = self.classify_item(item); - if let Some(attr) = attr { + let (attr, traits, item) = self.classify_item(item); + if attr.is_some() || !traits.is_empty() { let item = Annotatable::ImplItem(P(fully_configure!(self, item, noop_fold_impl_item))); - return self.collect_attr(attr, item, ExpansionKind::ImplItems).make_impl_items(); + return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems) + .make_impl_items(); } match item.node { @@ -1038,6 +1134,7 @@ impl<'feat> ExpansionConfig<'feat> { fn enable_trace_macros = trace_macros, fn enable_allow_internal_unstable = allow_internal_unstable, fn enable_custom_derive = custom_derive, + fn proc_macro_enabled = proc_macro, } } diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 66555d7d95dc..0636a78b2152 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -84,8 +84,17 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } } - pub fn add(&mut self, id: ast::NodeId, expansion: Expansion) { - let expansion = expansion.fold_with(self); + pub fn add(&mut self, id: ast::NodeId, expansion: Expansion, derives: Vec) { + let mut expansion = expansion.fold_with(self); + if let Expansion::Items(mut items) = expansion { + for derive in derives { + match self.remove(derive.as_placeholder_id()) { + Expansion::Items(derived_items) => items.extend(derived_items), + _ => unreachable!(), + } + } + expansion = Expansion::Items(items); + } self.expansions.insert(id, expansion); } diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index 974e86a57412..a7e2d82bb978 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -107,12 +107,10 @@ impl MultiItemModifier for ProcMacroDerive { } }); - let mut res = vec![Annotatable::Item(item)]; // Reassign spans of all expanded items to the input `item` // for better errors here. - res.extend(new_items.into_iter().flat_map(|item| { - ChangeSpan { span: span }.fold_item(item) - }).map(Annotatable::Item)); - res + new_items.into_iter().map(|item| { + Annotatable::Item(ChangeSpan { span: span }.fold_item(item).expect_one("")) + }).collect() } } diff --git a/src/test/compile-fail-fulldeps/gated-quote.rs b/src/test/compile-fail-fulldeps/gated-quote.rs index 51a9a87744a2..3480bd895bf1 100644 --- a/src/test/compile-fail-fulldeps/gated-quote.rs +++ b/src/test/compile-fail-fulldeps/gated-quote.rs @@ -39,18 +39,18 @@ impl ParseSess { pub fn main() { let ecx = &ParseSess; - let x = quote_tokens!(ecx, 3); //~ ERROR macro undefined: 'quote_tokens!' - let x = quote_expr!(ecx, 3); //~ ERROR macro undefined: 'quote_expr!' - let x = quote_ty!(ecx, 3); //~ ERROR macro undefined: 'quote_ty!' - let x = quote_method!(ecx, 3); //~ ERROR macro undefined: 'quote_method!' - let x = quote_item!(ecx, 3); //~ ERROR macro undefined: 'quote_item!' - let x = quote_pat!(ecx, 3); //~ ERROR macro undefined: 'quote_pat!' - let x = quote_arm!(ecx, 3); //~ ERROR macro undefined: 'quote_arm!' - let x = quote_stmt!(ecx, 3); //~ ERROR macro undefined: 'quote_stmt!' - let x = quote_matcher!(ecx, 3); //~ ERROR macro undefined: 'quote_matcher!' - let x = quote_attr!(ecx, 3); //~ ERROR macro undefined: 'quote_attr!' - let x = quote_arg!(ecx, 3); //~ ERROR macro undefined: 'quote_arg!' - let x = quote_block!(ecx, 3); //~ ERROR macro undefined: 'quote_block!' - let x = quote_meta_item!(ecx, 3); //~ ERROR macro undefined: 'quote_meta_item!' - let x = quote_path!(ecx, 3); //~ ERROR macro undefined: 'quote_path!' + let x = quote_tokens!(ecx, 3); //~ ERROR macro undefined: `quote_tokens` + let x = quote_expr!(ecx, 3); //~ ERROR macro undefined: `quote_expr` + let x = quote_ty!(ecx, 3); //~ ERROR macro undefined: `quote_ty` + let x = quote_method!(ecx, 3); //~ ERROR macro undefined: `quote_method` + let x = quote_item!(ecx, 3); //~ ERROR macro undefined: `quote_item` + let x = quote_pat!(ecx, 3); //~ ERROR macro undefined: `quote_pat` + let x = quote_arm!(ecx, 3); //~ ERROR macro undefined: `quote_arm` + let x = quote_stmt!(ecx, 3); //~ ERROR macro undefined: `quote_stmt` + let x = quote_matcher!(ecx, 3); //~ ERROR macro undefined: `quote_matcher` + let x = quote_attr!(ecx, 3); //~ ERROR macro undefined: `quote_attr` + let x = quote_arg!(ecx, 3); //~ ERROR macro undefined: `quote_arg` + let x = quote_block!(ecx, 3); //~ ERROR macro undefined: `quote_block` + let x = quote_meta_item!(ecx, 3); //~ ERROR macro undefined: `quote_meta_item` + let x = quote_path!(ecx, 3); //~ ERROR macro undefined: `quote_path` } diff --git a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs index b0cd42205326..d5d8d7b6ef85 100644 --- a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs +++ b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs @@ -14,5 +14,5 @@ extern crate macro_crate_test; fn main() { - assert_eq!(3, unexported_macro!()); //~ ERROR macro undefined: 'unexported_macro!' + assert_eq!(3, unexported_macro!()); //~ ERROR macro undefined: `unexported_macro` } diff --git a/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs b/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs index 8286d833e8d2..03c3960a1efe 100644 --- a/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs +++ b/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs @@ -12,12 +12,12 @@ // gate __register_diagnostic!(E0001); -//~^ ERROR macro undefined: '__register_diagnostic!' +//~^ ERROR macro undefined: `__register_diagnostic` fn main() { __diagnostic_used!(E0001); - //~^ ERROR macro undefined: '__diagnostic_used!' + //~^ ERROR macro undefined: `__diagnostic_used` } __build_diagnostic_array!(DIAGNOSTICS); -//~^ ERROR macro undefined: '__build_diagnostic_array!' +//~^ ERROR macro undefined: `__build_diagnostic_array` diff --git a/src/test/compile-fail/issue-11692.rs b/src/test/compile-fail/issue-11692.rs index 09cf97396140..7819fd4c1abc 100644 --- a/src/test/compile-fail/issue-11692.rs +++ b/src/test/compile-fail/issue-11692.rs @@ -10,9 +10,9 @@ fn main() { print!(test!()); - //~^ ERROR: macro undefined: 'test!' + //~^ ERROR: macro undefined: `test` //~^^ ERROR: format argument must be a string literal concat!(test!()); - //~^ ERROR: macro undefined: 'test!' + //~^ ERROR: macro undefined: `test` } diff --git a/src/test/compile-fail/issue-19734.rs b/src/test/compile-fail/issue-19734.rs index ab88b580ba10..fe0648c3713f 100644 --- a/src/test/compile-fail/issue-19734.rs +++ b/src/test/compile-fail/issue-19734.rs @@ -11,5 +11,5 @@ fn main() {} impl Type { - undef!(); //~ ERROR macro undefined: 'undef!' + undef!(); //~ ERROR macro undefined: `undef` } diff --git a/src/test/compile-fail/macro-error.rs b/src/test/compile-fail/macro-error.rs index f467ba3b1e19..3512b21961a1 100644 --- a/src/test/compile-fail/macro-error.rs +++ b/src/test/compile-fail/macro-error.rs @@ -16,5 +16,5 @@ fn main() { foo!(0); // Check that we report errors at macro definition, not expansion. let _: cfg!(foo) = (); //~ ERROR non-type macro in type position - derive!(); //~ ERROR macro undefined: 'derive!' + derive!(); //~ ERROR macro undefined: `derive` } diff --git a/src/test/compile-fail/macro_undefined.rs b/src/test/compile-fail/macro_undefined.rs index d9f86e3e62ac..d35428efaccb 100644 --- a/src/test/compile-fail/macro_undefined.rs +++ b/src/test/compile-fail/macro_undefined.rs @@ -18,8 +18,8 @@ mod m { } fn main() { - k!(); //~ ERROR macro undefined: 'k!' + k!(); //~ ERROR macro undefined: `k` //~^ HELP did you mean `kl!`? - kl!(); //~ ERROR macro undefined: 'kl!' + kl!(); //~ ERROR macro undefined: `kl` //~^ HELP have you added the `#[macro_use]` on the module/import? } diff --git a/src/test/compile-fail/self_type_keyword.rs b/src/test/compile-fail/self_type_keyword.rs index db6bcc611b82..b3ab96b79c49 100644 --- a/src/test/compile-fail/self_type_keyword.rs +++ b/src/test/compile-fail/self_type_keyword.rs @@ -25,7 +25,7 @@ pub fn main() { ref mut Self => (), //~^ ERROR expected identifier, found keyword `Self` Self!() => (), - //~^ ERROR macro undefined: 'Self!' + //~^ ERROR macro undefined: `Self` Foo { Self } => (), //~^ ERROR expected identifier, found keyword `Self` } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs index a253c6224aa6..b7374a07e427 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs @@ -20,6 +20,5 @@ use proc_macro::TokenStream; pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); assert!(input.contains("struct A;")); - assert!(input.contains("#[derive(Debug, PartialEq, Eq, Copy, Clone)]")); "".parse().unwrap() } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs index 4624891c1a32..67d828d92a70 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs @@ -19,6 +19,6 @@ use proc_macro::TokenStream; #[proc_macro_derive(AToB)] pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); - assert_eq!(input, "#[derive(Copy, Clone)]\nstruct A;"); + assert_eq!(input, "struct A;"); "struct B;".parse().unwrap() } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs index c18cda895325..bf793534d50c 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs @@ -22,6 +22,5 @@ pub fn derive(input: TokenStream) -> TokenStream { assert!(input.contains("#[B]")); assert!(input.contains("struct B {")); assert!(input.contains("#[C]")); - assert!(input.contains("#[derive(Debug, PartialEq, Eq, Copy, Clone)]")); "".parse().unwrap() }