diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 17185a6ab69f4..308e16b2fff18 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -393,7 +393,7 @@ impl<'a> LoweringContext<'a> { } fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span { - let mark = Mark::fresh(); + let mark = Mark::fresh(Mark::root()); mark.set_expn_info(codemap::ExpnInfo { call_site: span, callee: codemap::NameAndSpan { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 05f30f039c8f0..5e74c84cd4e62 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -17,7 +17,7 @@ use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex} use rustc::hir::def::{Def, Export}; use rustc::hir::map::{self, DefCollector}; use rustc::ty; -use syntax::ast::{self, Name, Ident}; +use syntax::ast::{self, Name, Ident, Path}; use syntax::attr::{self, HasAttrs}; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator}; @@ -110,7 +110,7 @@ impl<'a> base::Resolver for Resolver<'a> { } fn get_module_scope(&mut self, id: ast::NodeId) -> Mark { - let mark = Mark::fresh(); + let mark = Mark::fresh(Mark::root()); let module = self.module_map[&self.definitions.local_def_id(id)]; self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData { module: Cell::new(module), @@ -156,16 +156,20 @@ impl<'a> base::Resolver for Resolver<'a> { self.whitelisted_legacy_custom_derives.contains(&name) } - fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]) { + fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[(Mark, Path)]) { 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 unresolved = self.current_module.unresolved_invocations.borrow_mut(); + unresolved.remove(&mark); + for &(derive, _) in derives { + unresolved.insert(derive); + self.invocations.insert(derive, invocation); + } } + let mut visitor = BuildReducedGraphVisitor { resolver: self, legacy_scope: LegacyScope::Invocation(invocation), diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index fda026fec64ef..2bd0b87e11410 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -10,7 +10,7 @@ pub use self::SyntaxExtension::{MultiDecorator, MultiModifier, NormalTT, IdentTT}; -use ast::{self, Attribute, Name, PatKind, MetaItem}; +use ast::{self, Attribute, Name, PatKind, MetaItem, Path}; use attr::HasAttrs; use codemap::{self, CodeMap, Spanned, respan}; use syntax_pos::{Span, DUMMY_SP}; @@ -578,7 +578,7 @@ 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, derives: &[Mark]); + fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[(Mark, Path)]); fn add_builtin(&mut self, ident: ast::Ident, ext: Rc); fn resolve_imports(&mut self); @@ -604,7 +604,7 @@ 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, _derives: &[Mark]) {} + fn visit_expansion(&mut self, _invoc: Mark, _: &Expansion, _derives: &[(Mark, Path)]) {} fn add_builtin(&mut self, _ident: ast::Ident, _ext: Rc) {} fn resolve_imports(&mut self) {} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 1b3352f73ade7..c07b13cae848f 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -44,6 +44,7 @@ macro_rules! expansions { $(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => { #[derive(Copy, Clone, PartialEq, Eq)] pub enum ExpansionKind { OptExpr, $( $kind, )* } + #[derive(Clone)] pub enum Expansion { OptExpr(Option>), $( $kind($ty), )* } impl ExpansionKind { @@ -188,12 +189,30 @@ impl Invocation { pub struct MacroExpander<'a, 'b:'a> { pub cx: &'a mut ExtCtxt<'b>, + partial_expansions: HashMap, + full_expansions: HashMap, monotonic: bool, // c.f. `cx.monotonic_expander()` } +struct PartialExpansion { + expansion: Expansion, + derives: Vec<(Mark, Path)>, + expansion_kind: ExpansionKind, + expansion_data: ExpansionData, + unexpanded_children: usize, +} + +pub struct FullExpansion { + pub expansion: Expansion, + pub derives: Vec, +} + impl<'a, 'b> MacroExpander<'a, 'b> { pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self { - MacroExpander { cx: cx, monotonic: monotonic } + MacroExpander { + cx: cx, monotonic: monotonic, + partial_expansions: HashMap::new(), full_expansions: HashMap::new(), + } } pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { @@ -230,12 +249,12 @@ 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 mark = self.cx.current_expansion.mark; + let mut invocations = + self.collect_invocations(mark, expansion, Vec::new(), ExpansionKind::Items); 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 { @@ -249,8 +268,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { continue }; - let scope = - if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark }; + let mark = invoc.expansion_data.mark; + let scope = if self.monotonic { mark } else { orig_expansion_data.mark }; let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) { Ok(ext) => Some(ext), Err(Determinacy::Determined) => None, @@ -261,72 +280,44 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; progress = true; - let ExpansionData { depth, mark, .. } = invoc.expansion_data; self.cx.current_expansion = invoc.expansion_data.clone(); self.cx.current_expansion.mark = scope; - // FIXME(jseyfried): Refactor out the following logic - let (expansion, new_invocations) = if let Some(ext) = ext { + let new_invocations = if let Some(ext) = ext { if let Some(ext) = ext { + let expansion_kind = invoc.expansion_kind; let expansion = self.expand_invoc(invoc, ext); - self.collect_invocations(expansion, &[]) + self.collect_invocations(mark, expansion, Vec::new(), expansion_kind) } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind { let item = item .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs }); - let item_with_markers = - add_derived_markers(&mut self.cx, item.span(), &traits, item.clone()); - let derives = derives.entry(invoc.expansion_data.mark).or_insert_with(Vec::new); - - for path in &traits { - let mark = Mark::fresh(); - derives.push(mark); - let item = match self.cx.resolver.resolve_macro( - Mark::root(), path, MacroKind::Derive, false) { - Ok(ext) => match *ext { - SyntaxExtension::BuiltinDerive(..) => item_with_markers.clone(), - _ => item.clone(), - }, - _ => item.clone(), - }; - invocations.push(Invocation { - kind: InvocationKind::Derive { path: path.clone(), item: item }, - expansion_kind: invoc.expansion_kind, - expansion_data: ExpansionData { - mark: mark, - ..invoc.expansion_data.clone() - }, - }); - } + let item = add_derived_markers(&mut self.cx, item.span(), &traits, item); let expansion = invoc.expansion_kind - .expect_from_annotatables(::std::iter::once(item_with_markers)); - self.collect_invocations(expansion, derives) + .expect_from_annotatables(::std::iter::once(item)); + self.collect_invocations(mark, expansion, traits, invoc.expansion_kind) } else { unreachable!() } } else { - self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()), &[]) + let dummy = invoc.expansion_kind.dummy(invoc.span()); + self.collect_invocations(mark, dummy, Vec::new(), invoc.expansion_kind) }; - if expansions.len() < depth { - expansions.push(Vec::new()); - } - expansions[depth - 1].push((mark, expansion)); if !self.cx.ecfg.single_step { invocations.extend(new_invocations.into_iter().rev()); } } self.cx.current_expansion = orig_expansion_data; + self.placeholder_expander().remove(NodeId::placeholder_from_mark(mark)) + } - let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); - while let Some(expansions) = expansions.pop() { - for (mark, expansion) in expansions.into_iter().rev() { - let derives = derives.remove(&mark).unwrap_or_else(Vec::new); - placeholder_expander.add(NodeId::placeholder_from_mark(mark), expansion, derives); - } + fn placeholder_expander<'c>(&'c mut self) -> PlaceholderExpander<'c, 'b> { + PlaceholderExpander { + cx: self.cx, + expansions: &mut self.full_expansions, + monotonic: self.monotonic, } - - expansion.fold_with(&mut placeholder_expander) } fn resolve_imports(&mut self) { @@ -337,9 +328,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } - fn collect_invocations(&mut self, expansion: Expansion, derives: &[Mark]) - -> (Expansion, Vec) { - let result = { + fn collect_invocations(&mut self, + mut mark: Mark, + expansion: Expansion, + traits: Vec, + expansion_kind: ExpansionKind) + -> Vec { + let (expansion, mut invocations) = { let mut collector = InvocationCollector { cfg: StripUnconfigured { should_test: self.cx.ecfg.should_test, @@ -347,20 +342,77 @@ impl<'a, 'b> MacroExpander<'a, 'b> { features: self.cx.ecfg.features, }, cx: self.cx, + mark: mark, invocations: Vec::new(), monotonic: self.monotonic, }; (expansion.fold_with(&mut collector), collector.invocations) }; + let mark_parent = mark.parent(); + let derives: Vec<_> = + traits.into_iter().map(|path| (Mark::fresh(mark_parent), path)).collect(); + if derives.len() > 0 { + self.partial_expansions.get_mut(&mark_parent).unwrap().unexpanded_children += + derives.len(); + } + 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, derives); + self.cx.resolver.visit_expansion(mark, &expansion, &derives); self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count; } - result + self.partial_expansions.insert(mark, PartialExpansion { + expansion: expansion, derives: derives, expansion_kind: expansion_kind, + expansion_data: self.cx.current_expansion.clone(), + unexpanded_children: invocations.len(), + }); + + if !invocations.is_empty() { + return invocations; + } + + loop { + let partial_expansion = self.partial_expansions.remove(&mark).unwrap(); + let expansion = partial_expansion.expansion.fold_with(&mut self.placeholder_expander()); + + let PartialExpansion { expansion_kind, ref expansion_data, .. } = partial_expansion; + let derives = partial_expansion.derives.into_iter().map(|(mark, path)| { + let item = match expansion.clone() { + Expansion::Items(mut items) => Annotatable::Item(items.pop().unwrap()), + Expansion::TraitItems(mut items) => + Annotatable::TraitItem(P(items.pop().unwrap())), + Expansion::ImplItems(mut items) => + Annotatable::ImplItem(P(items.pop().unwrap())), + _ => panic!("expected item"), + }; + invocations.push(Invocation { + kind: InvocationKind::Derive { path: path, item: item }, + expansion_kind: expansion_kind, + expansion_data: ExpansionData { mark: mark, ..expansion_data.clone() }, + }); + mark + }).collect(); + + self.full_expansions + .insert(mark, FullExpansion { expansion: expansion, derives: derives }); + + if mark == Mark::root() { + break + } + mark = mark.parent(); + if let Some(partial_expansion) = self.partial_expansions.get_mut(&mark) { + partial_expansion.unexpanded_children -= 1; + if partial_expansion.unexpanded_children == 0 { + continue + } + } + break + } + + invocations } fn expand_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { @@ -661,6 +713,7 @@ impl<'a> Parser<'a> { struct InvocationCollector<'a, 'b: 'a> { cx: &'a mut ExtCtxt<'b>, + mark: Mark, cfg: StripUnconfigured<'a>, invocations: Vec, monotonic: bool, @@ -677,7 +730,7 @@ macro_rules! fully_configure { impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion { - let mark = Mark::fresh(); + let mark = Mark::fresh(self.mark); self.invocations.push(Invocation { kind: kind, expansion_kind: expansion_kind, @@ -992,7 +1045,6 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId { if self.monotonic { - assert_eq!(id, ast::DUMMY_NODE_ID); self.cx.resolver.next_node_id() } else { id diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 4fb138d506a8e..6794f84d1bad2 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -11,7 +11,7 @@ use ast::{self, NodeId}; use codemap::{DUMMY_SP, dummy_spanned}; use ext::base::ExtCtxt; -use ext::expand::{Expansion, ExpansionKind}; +use ext::expand::{Expansion, ExpansionKind, FullExpansion}; use ext::hygiene::Mark; use tokenstream::TokenStream; use fold::*; @@ -70,22 +70,15 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion { } pub struct PlaceholderExpander<'a, 'b: 'a> { - expansions: HashMap, - cx: &'a mut ExtCtxt<'b>, - monotonic: bool, + pub expansions: &'a mut HashMap, + pub cx: &'a mut ExtCtxt<'b>, + pub monotonic: bool, } impl<'a, 'b> PlaceholderExpander<'a, 'b> { - pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self { - PlaceholderExpander { - cx: cx, - expansions: HashMap::new(), - monotonic: monotonic, - } - } - - pub fn add(&mut self, id: ast::NodeId, expansion: Expansion, derives: Vec) { - let mut expansion = expansion.fold_with(self); + pub fn remove(&mut self, id: ast::NodeId) -> Expansion { + let FullExpansion { mut expansion, derives } = + self.expansions.remove(&id.placeholder_to_mark()).unwrap(); if let Expansion::Items(mut items) = expansion { for derive in derives { match self.remove(NodeId::placeholder_from_mark(derive)) { @@ -95,11 +88,7 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } expansion = Expansion::Items(items); } - self.expansions.insert(id, expansion); - } - - fn remove(&mut self, id: ast::NodeId) -> Expansion { - self.expansions.remove(&id).unwrap() + expansion } } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index c7820a15fb3d2..3ebdc94bbd524 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -21,7 +21,7 @@ use tokenstream::TokenStream; /// call to codemap's is_internal check. /// The expanded code uses the unstable `#[prelude_import]` attribute. fn ignored_span(sp: Span) -> Span { - let mark = Mark::fresh(); + let mark = Mark::fresh(Mark::root()); mark.set_expn_info(ExpnInfo { call_site: DUMMY_SP, callee: NameAndSpan { diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 50380626d7f0d..da90353ee7270 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -277,7 +277,7 @@ fn generate_test_harness(sess: &ParseSess, let mut cleaner = EntryPointCleaner { depth: 0 }; let krate = cleaner.fold_crate(krate); - let mark = Mark::fresh(); + let mark = Mark::fresh(Mark::root()); let mut cx: TestCtxt = TestCtxt { sess: sess, span_diagnostic: sd, diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index b01ef65e5fe5e..4a14273fbd2ac 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -13,7 +13,7 @@ use std::panic; use errors::FatalError; use proc_macro::{TokenStream, __internal}; use syntax::ast::{self, ItemKind, Attribute, Mac}; -use syntax::attr::{mark_used, mark_known}; +use syntax::attr::{HasAttrs, mark_used, mark_known}; use syntax::codemap::Span; use syntax::ext::base::*; use syntax::fold::Folder; @@ -71,6 +71,11 @@ impl MultiItemModifier for ProcMacroDerive { } } + let item = item.map_attrs(|mut attrs| { + attrs.retain(|a| a.path != "structural_match" && a.path != "rustc_copy_clone_marker"); + attrs + }); + // Mark attributes as known, and used. MarkAttrs(&self.attrs).visit_item(&item); diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 1ff0fec1c96a6..a8df20cf55477 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -347,21 +347,15 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>) /// This method helps to extract all the type parameters referenced from a /// type. For a type parameter ``, it looks for either a `TyPath` that /// is not global and starts with `T`, or a `TyQPath`. -fn find_type_parameters(ty: &ast::Ty, - ty_param_names: &[ast::Name], - span: Span, - cx: &ExtCtxt) - -> Vec> { +fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec> { use syntax::visit; - struct Visitor<'a, 'b: 'a> { - cx: &'a ExtCtxt<'b>, - span: Span, + struct Visitor<'a> { ty_param_names: &'a [ast::Name], types: Vec>, } - impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> { + impl<'a> visit::Visitor<'a> for Visitor<'a> { fn visit_ty(&mut self, ty: &'a ast::Ty) { if let ast::TyKind::Path(_, ref path) = ty.node { if let Some(segment) = path.segments.first() { @@ -373,18 +367,11 @@ fn find_type_parameters(ty: &ast::Ty, visit::walk_ty(self, ty) } - - fn visit_mac(&mut self, mac: &ast::Mac) { - let span = Span { ctxt: self.span.ctxt, ..mac.span }; - self.cx.span_err(span, "`derive` cannot be used on items with type macros"); - } } let mut visitor = Visitor { ty_param_names: ty_param_names, types: Vec::new(), - span: span, - cx: cx, }; visit::Visitor::visit_ty(&mut visitor, ty); @@ -571,7 +558,7 @@ impl<'a> TraitDef<'a> { let mut processed_field_types = HashSet::new(); for field_ty in field_tys { - let tys = find_type_parameters(&field_ty, &ty_param_names, self.span, cx); + let tys = find_type_parameters(&field_ty, &ty_param_names); for ty in tys { // if we have already handled this type, skip it diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index b2bb43e41ed9e..24e412e93cdb3 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -168,7 +168,7 @@ fn call_intrinsic(cx: &ExtCtxt, } else { // Avoid instability errors with user defined curstom derives, cc #36316 let mut info = cx.current_expansion.mark.expn_info().unwrap(); info.callee.allow_internal_unstable = true; - let mark = Mark::fresh(); + let mark = Mark::fresh(Mark::root()); mark.set_expn_info(info); span.ctxt = SyntaxContext::empty().apply_mark(mark); } diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index bb89caab709b0..dd0d1c4e746c2 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -361,7 +361,7 @@ fn mk_registrar(cx: &mut ExtCtxt, custom_derives: &[ProcMacroDerive], custom_attrs: &[ProcMacroDef], custom_macros: &[ProcMacroDef]) -> P { - let mark = Mark::fresh(); + let mark = Mark::fresh(Mark::root()); mark.set_expn_info(ExpnInfo { call_site: DUMMY_SP, callee: NameAndSpan { diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 8a9ff647b3ea1..cf524af2c1632 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -37,10 +37,16 @@ pub struct SyntaxContextData { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, RustcEncodable, RustcDecodable)] pub struct Mark(u32); +#[derive(Default)] +struct MarkData { + parent: Mark, + expn_info: Option, +} + impl Mark { - pub fn fresh() -> Self { + pub fn fresh(parent: Mark) -> Self { HygieneData::with(|data| { - data.marks.push(None); + data.marks.push(MarkData { parent: parent, expn_info: None }); Mark(data.marks.len() as u32 - 1) }) } @@ -58,17 +64,21 @@ impl Mark { Mark(raw) } + pub fn parent(self) -> Mark { + HygieneData::with(|data| data.marks[self.0 as usize].parent) + } + pub fn expn_info(self) -> Option { - HygieneData::with(|data| data.marks[self.0 as usize].clone()) + HygieneData::with(|data| data.marks[self.0 as usize].expn_info.clone()) } pub fn set_expn_info(self, info: ExpnInfo) { - HygieneData::with(|data| data.marks[self.0 as usize] = Some(info)) + HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info)) } } struct HygieneData { - marks: Vec>, + marks: Vec, syntax_contexts: Vec, markings: HashMap<(SyntaxContext, Mark), SyntaxContext>, } @@ -76,7 +86,7 @@ struct HygieneData { impl HygieneData { fn new() -> Self { HygieneData { - marks: vec![None], + marks: vec![MarkData::default()], syntax_contexts: vec![SyntaxContextData { outer_mark: Mark::root(), prev_ctxt: SyntaxContext::empty(), diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/type_macros_example.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/type_macros_example.rs new file mode 100644 index 0000000000000..ca7e10e11d1ff --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/type_macros_example.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. + +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Example)] +pub fn example(input: TokenStream) -> TokenStream { + assert!(input.to_string().contains("i32")); + "".parse().unwrap() +} diff --git a/src/test/run-pass-fulldeps/proc-macro/type_macros.rs b/src/test/run-pass-fulldeps/proc-macro/type_macros.rs new file mode 100644 index 0000000000000..a9c6e273e06c6 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/type_macros.rs @@ -0,0 +1,26 @@ +// 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. + +// aux-build:type_macros_example.rs + +#![feature(proc_macro)] + +extern crate type_macros_example; + +use type_macros_example::Example; + +macro_rules! m { () => { i32 } } + +#[derive(Example)] +struct S { + x: m!(), +} + +fn main() {} diff --git a/src/test/compile-fail/issue-32950.rs b/src/test/run-pass/issue-32950.rs similarity index 77% rename from src/test/compile-fail/issue-32950.rs rename to src/test/run-pass/issue-32950.rs index 20e5b1d72d3d7..bcbc0ee3df63b 100644 --- a/src/test/compile-fail/issue-32950.rs +++ b/src/test/run-pass/issue-32950.rs @@ -10,9 +10,12 @@ #![feature(concat_idents)] -#[derive(Debug)] //~ NOTE in this expansion -struct Baz( - concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros +#[derive(Debug)] +struct Baz(T, + concat_idents!(Foo, Bar) ); +#[derive(Debug)] +struct FooBar; + fn main() {}