diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index ea3112b2463..a1699784b9d 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 946448eaaee..ba14a153ed2 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) })