From 961ba8f9efbb51d80e7e73a609f6587c0ffa0623 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 16 Jun 2019 18:58:39 +0300 Subject: [PATCH 1/8] syntax: Factor out common fields from `SyntaxExtension` variants --- .../src/language-features/plugin.md | 2 +- src/librustc_allocator/expand.rs | 2 +- src/librustc_metadata/creader.rs | 50 +++-- src/librustc_metadata/cstore_impl.rs | 13 +- src/librustc_metadata/decoder.rs | 7 +- src/librustc_plugin/registry.rs | 22 +-- src/librustc_resolve/build_reduced_graph.rs | 11 +- src/librustc_resolve/macros.rs | 32 ++-- src/librustdoc/clean/inline.rs | 12 +- .../passes/collect_intra_doc_links.rs | 4 +- src/libsyntax/ext/base.rs | 148 +++++++++------ src/libsyntax/ext/derive.rs | 2 +- src/libsyntax/ext/expand.rs | 178 +++++------------- src/libsyntax/ext/tt/macro_rules.rs | 12 +- src/libsyntax/std_inject.rs | 2 +- src/libsyntax/test.rs | 2 +- src/libsyntax_ext/deriving/mod.rs | 21 ++- src/libsyntax_ext/lib.rs | 69 +++---- src/libsyntax_ext/proc_macro_decls.rs | 7 +- src/libsyntax_ext/test.rs | 2 +- src/libsyntax_ext/test_case.rs | 2 +- .../auxiliary/plugin-args.rs | 18 +- 22 files changed, 269 insertions(+), 349 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 1994cf491889b..0e38e2865d893 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -132,7 +132,7 @@ The advantages over a simple `fn(&str) -> u32` are: In addition to procedural macros, you can define new [`derive`](../../reference/attributes/derive.md)-like attributes and other kinds of extensions. See `Registry::register_syntax_extension` and the -`SyntaxExtension` enum. For a more involved macro example, see +`SyntaxExtension` struct. For a more involved macro example, see [`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs). diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index 3ec06b17aff22..ecc165ca5ea9f 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -91,7 +91,7 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> { call_site: item.span, // use the call site of the static def_site: None, format: MacroAttribute(Symbol::intern(name)), - allow_internal_unstable: Some(vec![sym::rustc_attrs].into()), + allow_internal_unstable: Some([sym::rustc_attrs][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: self.sess.edition, diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 5fef8e53e1d0c..d3d00fa4adcfe 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -26,7 +26,7 @@ use std::{cmp, fs}; use syntax::ast; use syntax::attr; -use syntax::ext::base::SyntaxExtension; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::symbol::{Symbol, sym}; use syntax::visit; use syntax::{span_err, span_fatal}; @@ -611,33 +611,31 @@ impl<'a> CrateLoader<'a> { }; let extensions = decls.iter().map(|&decl| { - match decl { + let (name, kind, helper_attrs) = match decl { ProcMacro::CustomDerive { trait_name, attributes, client } => { - let attrs = attributes.iter().cloned().map(Symbol::intern).collect::>(); - (trait_name, SyntaxExtension::Derive( - Box::new(ProcMacroDerive { - client, - attrs: attrs.clone(), - }), - attrs, - root.edition, - )) + let helper_attrs = + attributes.iter().cloned().map(Symbol::intern).collect::>(); + ( + trait_name, + SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { + client, attrs: helper_attrs.clone() + })), + helper_attrs, + ) } - ProcMacro::Attr { name, client } => { - (name, SyntaxExtension::Attr( - Box::new(AttrProcMacro { client }), - root.edition, - )) - } - ProcMacro::Bang { name, client } => { - (name, SyntaxExtension::Bang { - expander: Box::new(BangProcMacro { client }), - allow_internal_unstable: None, - edition: root.edition, - }) - } - } - }).map(|(name, ext)| (Symbol::intern(name), Lrc::new(ext))).collect(); + ProcMacro::Attr { name, client } => ( + name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new() + ), + ProcMacro::Bang { name, client } => ( + name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new() + ) + }; + + (Symbol::intern(name), Lrc::new(SyntaxExtension { + helper_attrs, + ..SyntaxExtension::default(kind, root.edition) + })) + }).collect(); // Intentionally leak the dynamic library. We can't ever unload it // since the library can make things that will live arbitrarily long. diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 86536b179f222..04a9c4e9a1a11 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -30,9 +30,11 @@ use syntax::ast; use syntax::attr; use syntax::source_map; use syntax::edition::Edition; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::parse::source_file_to_stream; use syntax::parse::parser::emit_unclosed_delims; use syntax::symbol::{Symbol, sym}; +use syntax_ext::proc_macro_impl::BangProcMacro; use syntax_pos::{Span, NO_EXPANSION, FileName}; use rustc_data_structures::bit_set::BitSet; @@ -427,14 +429,11 @@ impl cstore::CStore { if let Some(ref proc_macros) = data.proc_macros { return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone()); } else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote { - use syntax::ext::base::SyntaxExtension; - use syntax_ext::proc_macro_impl::BangProcMacro; - let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); - let ext = SyntaxExtension::Bang { - expander: Box::new(BangProcMacro { client }), - allow_internal_unstable: Some(vec![sym::proc_macro_def_site].into()), - edition: data.root.edition, + let kind = SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })); + let ext = SyntaxExtension { + allow_internal_unstable: Some([sym::proc_macro_def_site][..].into()), + ..SyntaxExtension::default(kind, data.root.edition) }; return LoadedMacro::ProcMacro(Lrc::new(ext)); } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 4bafe16b8e66d..a776966bda489 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -511,8 +511,9 @@ impl<'a, 'tcx> CrateMetadata { if !self.is_proc_macro(index) { self.entry(index).kind.def_kind() } else { - let kind = self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.kind(); - Some(DefKind::Macro(kind)) + Some(DefKind::Macro( + self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.macro_kind() + )) } } @@ -739,7 +740,7 @@ impl<'a, 'tcx> CrateMetadata { if id == CRATE_DEF_INDEX { for (id, &(name, ref ext)) in proc_macros.iter().enumerate() { let res = Res::Def( - DefKind::Macro(ext.kind()), + DefKind::Macro(ext.macro_kind()), self.local_def_id(DefIndex::from_proc_macro_index(id)), ); let ident = Ident::with_empty_ctxt(name); diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index dd5e42684c427..16d484e2a98f2 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -4,9 +4,8 @@ use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint}; use rustc::session::Session; use rustc::util::nodemap::FxHashMap; -use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension}; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension}; use syntax::ext::base::MacroExpanderFn; -use syntax::ext::hygiene::Transparency; use syntax::symbol::{Symbol, sym}; use syntax::ast; use syntax::feature_gate::AttributeType; @@ -89,8 +88,8 @@ impl<'a> Registry<'a> { if name == sym::macro_rules { panic!("user-defined macros may not be named `macro_rules`"); } - if let SyntaxExtension::LegacyBang { def_info: ref mut def_info @ None, .. } = extension { - *def_info = Some((ast::CRATE_NODE_ID, self.krate_span)); + if extension.def_info.is_none() { + extension.def_info = Some((ast::CRATE_NODE_ID, self.krate_span)); } self.syntax_exts.push((name, extension)); } @@ -98,19 +97,12 @@ impl<'a> Registry<'a> { /// Register a macro of the usual kind. /// /// This is a convenience wrapper for `register_syntax_extension`. - /// It builds for you a `SyntaxExtension::LegacyBang` that calls `expander`, + /// It builds for you a `SyntaxExtensionKind::LegacyBang` that calls `expander`, /// and also takes care of interning the macro's name. pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) { - self.register_syntax_extension(Symbol::intern(name), SyntaxExtension::LegacyBang { - expander: Box::new(expander), - def_info: None, - transparency: Transparency::SemiTransparent, - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - unstable_feature: None, - edition: self.sess.edition(), - }); + let kind = SyntaxExtensionKind::LegacyBang(Box::new(expander)); + let ext = SyntaxExtension::default(kind, self.sess.edition()); + self.register_syntax_extension(Symbol::intern(name), ext); } /// Register a compiler lint pass. diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e3cd2948d7af5..bb4edf355f8b5 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -29,7 +29,7 @@ use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}; use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant}; -use syntax::ext::base::{MacroKind, SyntaxExtension}; +use syntax::ext::base::{MacroKind, SyntaxExtension, SyntaxExtensionKind}; use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; @@ -772,9 +772,12 @@ impl<'a> Resolver<'a> { pub fn get_macro(&mut self, res: Res) -> Lrc { let def_id = match res { Res::Def(DefKind::Macro(..), def_id) => def_id, - Res::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::NonMacroAttr { - mark_used: attr_kind == NonMacroAttrKind::Tool, - }), + Res::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::default( + SyntaxExtensionKind::NonMacroAttr { + mark_used: attr_kind == NonMacroAttrKind::Tool + }, + self.session.edition(), + )), _ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"), }; if let Some(ext) = self.macro_map.get(&def_id) { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 2369bddf4f75f..89e28330be7e3 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -15,7 +15,7 @@ use syntax::ast::{self, Ident}; use syntax::attr; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy}; -use syntax::ext::base::{MacroKind, SyntaxExtension}; +use syntax::ext::base::{MacroKind, SyntaxExtension, SyntaxExtensionKind}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; @@ -174,7 +174,7 @@ impl<'a> base::Resolver for Resolver<'a> { krate: CrateNum::BuiltinMacros, index: DefIndex::from(self.macro_map.len()), }; - let kind = ext.kind(); + let kind = ext.macro_kind(); self.macro_map.insert(def_id, ext); let binding = self.arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Res(Res::Def(DefKind::Macro(kind), def_id), false), @@ -211,7 +211,8 @@ impl<'a> base::Resolver for Resolver<'a> { Ok((res, ext)) => (res, ext), Err(Determinacy::Determined) if kind == MacroKind::Attr => { // Replace unresolved attributes with used inert attributes for better recovery. - return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr { mark_used: true }))); + let kind = SyntaxExtensionKind::NonMacroAttr { mark_used: true }; + return Ok(Some(Lrc::new(SyntaxExtension::default(kind, self.session.edition())))); } Err(determinacy) => return Err(determinacy), }; @@ -226,7 +227,7 @@ impl<'a> base::Resolver for Resolver<'a> { self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id; self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark, normal_module_def_id); - invoc.expansion_data.mark.set_default_transparency(ext.default_transparency()); + invoc.expansion_data.mark.set_default_transparency(ext.default_transparency); } Ok(Some(ext)) @@ -241,11 +242,7 @@ impl<'a> base::Resolver for Resolver<'a> { fn check_unused_macros(&self) { for did in self.unused_macros.iter() { - let id_span = match *self.macro_map[did] { - SyntaxExtension::LegacyBang { def_info, .. } => def_info, - _ => None, - }; - if let Some((id, span)) = id_span { + if let Some((id, span)) = self.macro_map[did].def_info { let lint = lint::builtin::UNUSED_MACROS; let msg = "unused macro definition"; self.session.buffer_lint(lint, id, span, msg); @@ -585,17 +582,12 @@ impl<'a> Resolver<'a> { let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope }; match self.resolve_macro_to_res(derive, MacroKind::Derive, &parent_scope, true, force) { - Ok((_, ext)) => { - if let SyntaxExtension::Derive(_, helpers, _) = &*ext { - if helpers.contains(&ident.name) { - let binding = - (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), - ty::Visibility::Public, derive.span, Mark::root()) - .to_name_binding(self.arenas); - result = Ok((binding, Flags::empty())); - break; - } - } + Ok((_, ext)) => if ext.helper_attrs.contains(&ident.name) { + let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), + ty::Visibility::Public, derive.span, Mark::root()) + .to_name_binding(self.arenas); + result = Ok((binding, Flags::empty())); + break; } Err(Determinacy::Determined) => {} Err(Determinacy::Undetermined) => diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c14ae5932af47..9259b3b5d3abb 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -3,7 +3,7 @@ use std::iter::once; use syntax::ast; -use syntax::ext::base::{MacroKind, SyntaxExtension}; +use syntax::ext::base::MacroKind; use syntax::symbol::sym; use syntax_pos::Span; @@ -470,18 +470,12 @@ fn build_macro(cx: &DocContext<'_>, did: DefId, name: ast::Name) -> clean::ItemE }) } LoadedMacro::ProcMacro(ext) => { - let helpers = match &*ext { - &SyntaxExtension::Derive(_, ref syms, ..) => { syms.clean(cx) } - _ => Vec::new(), - }; - clean::ProcMacroItem(clean::ProcMacro { - kind: ext.kind(), - helpers, + kind: ext.macro_kind(), + helpers: ext.helper_attrs.clean(cx), }) } } - } /// A trait's generics clause actually contains all of the predicates for all of diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 7fbfc3e1fc0f4..68b96a408294b 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -423,7 +423,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { /// Resolves a string as a macro. fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option { - use syntax::ext::base::{MacroKind, SyntaxExtension}; + use syntax::ext::base::{MacroKind, SyntaxExtensionKind}; let segment = ast::PathSegment::from_ident(Ident::from_str(path_str)); let path = ast::Path { segments: vec![segment], span: DUMMY_SP }; cx.enter_resolver(|resolver| { @@ -433,7 +433,7 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option { if let Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) = res { // skip proc-macro stubs, they'll cause `get_macro` to crash } else { - if let SyntaxExtension::LegacyBang { .. } = *resolver.get_macro(res) { + if let SyntaxExtensionKind::LegacyBang(..) = resolver.get_macro(res).kind { return Some(res.map_id(|_| panic!("unexpected id"))); } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 38b7dee40c447..04cef0bba24bf 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -15,6 +15,7 @@ use crate::tokenstream::{self, TokenStream}; use errors::{DiagnosticBuilder, DiagnosticId}; use smallvec::{smallvec, SmallVec}; use syntax_pos::{Span, MultiSpan, DUMMY_SP}; +use syntax_pos::hygiene::{ExpnInfo, ExpnFormat}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; @@ -548,37 +549,19 @@ impl MacroKind { } } -/// An enum representing the different kinds of syntax extensions. -pub enum SyntaxExtension { +/// A syntax extension kind. +pub enum SyntaxExtensionKind { /// A token-based function-like macro. - Bang { + Bang( /// An expander with signature TokenStream -> TokenStream. - expander: Box, - /// Whitelist of unstable features that are treated as stable inside this macro. - allow_internal_unstable: Option>, - /// Edition of the crate in which this macro is defined. - edition: Edition, - }, + Box, + ), /// An AST-based function-like macro. - LegacyBang { + LegacyBang( /// An expander with signature TokenStream -> AST. - expander: Box, - /// Some info about the macro's definition point. - def_info: Option<(ast::NodeId, Span)>, - /// Hygienic properties of identifiers produced by this macro. - transparency: Transparency, - /// Whitelist of unstable features that are treated as stable inside this macro. - allow_internal_unstable: Option>, - /// Suppresses the `unsafe_code` lint for code produced by this macro. - allow_internal_unsafe: bool, - /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro. - local_inner_macros: bool, - /// The macro's feature name and tracking issue number if it is unstable. - unstable_feature: Option<(Symbol, u32)>, - /// Edition of the crate in which this macro is defined. - edition: Edition, - }, + Box, + ), /// A token-based attribute macro. Attr( @@ -586,8 +569,6 @@ pub enum SyntaxExtension { /// The first TokenSteam is the attribute itself, the second is the annotated item. /// The produced TokenSteam replaces the input TokenSteam. Box, - /// Edition of the crate in which this macro is defined. - Edition, ), /// An AST-based attribute macro. @@ -599,7 +580,8 @@ pub enum SyntaxExtension { ), /// A trivial attribute "macro" that does nothing, - /// only keeps the attribute and marks it as known. + /// only keeps the attribute and marks it as inert, + /// thus making it ineligible for further expansion. NonMacroAttr { /// Suppresses the `unused_attributes` lint for this attribute. mark_used: bool, @@ -610,10 +592,6 @@ pub enum SyntaxExtension { /// An expander with signature TokenStream -> TokenStream (not yet). /// The produced TokenSteam is appended to the input TokenSteam. Box, - /// Names of helper attributes registered by this macro. - Vec, - /// Edition of the crate in which this macro is defined. - Edition, ), /// An AST-based derive macro. @@ -624,42 +602,90 @@ pub enum SyntaxExtension { ), } +/// A struct representing a macro definition in "lowered" form ready for expansion. +pub struct SyntaxExtension { + /// A syntax extension kind. + pub kind: SyntaxExtensionKind, + /// Some info about the macro's definition point. + pub def_info: Option<(ast::NodeId, Span)>, + /// Hygienic properties of spans produced by this macro by default. + pub default_transparency: Transparency, + /// Whitelist of unstable features that are treated as stable inside this macro. + pub allow_internal_unstable: Option>, + /// Suppresses the `unsafe_code` lint for code produced by this macro. + pub allow_internal_unsafe: bool, + /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro. + pub local_inner_macros: bool, + /// The macro's feature name and tracking issue number if it is unstable. + pub unstable_feature: Option<(Symbol, u32)>, + /// Names of helper attributes registered by this macro. + pub helper_attrs: Vec, + /// Edition of the crate in which this macro is defined. + pub edition: Edition, +} + +impl SyntaxExtensionKind { + /// When a syntax extension is constructed, + /// its transparency can often be inferred from its kind. + fn default_transparency(&self) -> Transparency { + match self { + SyntaxExtensionKind::Bang(..) | + SyntaxExtensionKind::Attr(..) | + SyntaxExtensionKind::Derive(..) | + SyntaxExtensionKind::NonMacroAttr { .. } => Transparency::Opaque, + SyntaxExtensionKind::LegacyBang(..) | + SyntaxExtensionKind::LegacyAttr(..) | + SyntaxExtensionKind::LegacyDerive(..) => Transparency::SemiTransparent, + } + } +} + impl SyntaxExtension { /// Returns which kind of macro calls this syntax extension. - pub fn kind(&self) -> MacroKind { - match *self { - SyntaxExtension::Bang { .. } | - SyntaxExtension::LegacyBang { .. } => MacroKind::Bang, - SyntaxExtension::Attr(..) | - SyntaxExtension::LegacyAttr(..) | - SyntaxExtension::NonMacroAttr { .. } => MacroKind::Attr, - SyntaxExtension::Derive(..) | - SyntaxExtension::LegacyDerive(..) => MacroKind::Derive, + pub fn macro_kind(&self) -> MacroKind { + match self.kind { + SyntaxExtensionKind::Bang(..) | + SyntaxExtensionKind::LegacyBang(..) => MacroKind::Bang, + SyntaxExtensionKind::Attr(..) | + SyntaxExtensionKind::LegacyAttr(..) | + SyntaxExtensionKind::NonMacroAttr { .. } => MacroKind::Attr, + SyntaxExtensionKind::Derive(..) | + SyntaxExtensionKind::LegacyDerive(..) => MacroKind::Derive, } } - pub fn default_transparency(&self) -> Transparency { - match *self { - SyntaxExtension::LegacyBang { transparency, .. } => transparency, - SyntaxExtension::Bang { .. } | - SyntaxExtension::Attr(..) | - SyntaxExtension::Derive(..) | - SyntaxExtension::NonMacroAttr { .. } => Transparency::Opaque, - SyntaxExtension::LegacyAttr(..) | - SyntaxExtension::LegacyDerive(..) => Transparency::SemiTransparent, + /// Constructs a syntax extension with default properties. + pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension { + SyntaxExtension { + def_info: None, + default_transparency: kind.default_transparency(), + allow_internal_unstable: None, + allow_internal_unsafe: false, + local_inner_macros: false, + unstable_feature: None, + helper_attrs: Vec::new(), + edition, + kind, } } - pub fn edition(&self, default_edition: Edition) -> Edition { - match *self { - SyntaxExtension::Bang { edition, .. } | - SyntaxExtension::LegacyBang { edition, .. } | - SyntaxExtension::Attr(.., edition) | - SyntaxExtension::Derive(.., edition) => edition, - // Unstable legacy stuff - SyntaxExtension::NonMacroAttr { .. } | - SyntaxExtension::LegacyAttr(..) | - SyntaxExtension::LegacyDerive(..) => default_edition, + fn expn_format(&self, symbol: Symbol) -> ExpnFormat { + match self.kind { + SyntaxExtensionKind::Bang(..) | + SyntaxExtensionKind::LegacyBang(..) => ExpnFormat::MacroBang(symbol), + _ => ExpnFormat::MacroAttribute(symbol), + } + } + + crate fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo { + ExpnInfo { + call_site, + def_site: self.def_info.map(|(_, span)| span), + format: self.expn_format(Symbol::intern(format)), + allow_internal_unstable: self.allow_internal_unstable.clone(), + allow_internal_unsafe: self.allow_internal_unsafe, + local_inner_macros: self.local_inner_macros, + edition: self.edition, } } } diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index a2cf4a2a82d8d..33620cb80f940 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -64,7 +64,7 @@ pub fn add_derived_markers(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P call_site: span, def_site: None, format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), - allow_internal_unstable: Some(vec![sym::rustc_attrs, sym::structural_match].into()), + allow_internal_unstable: Some([sym::rustc_attrs, sym::structural_match][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: cx.parse_sess.edition, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 3fa96c60bff67..4e759c5e52865 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1,7 +1,7 @@ use crate::ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path}; use crate::ast::{MacStmtStyle, StmtKind, ItemKind}; use crate::attr::{self, HasAttrs}; -use crate::source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan}; +use crate::source_map::{dummy_spanned, respan}; use crate::config::StripUnconfigured; use crate::ext::base::*; use crate::ext::derive::{add_derived_markers, collect_derives}; @@ -22,7 +22,6 @@ use crate::util::map_in_place::MapInPlace; use errors::{Applicability, FatalError}; use smallvec::{smallvec, SmallVec}; use syntax_pos::{Span, DUMMY_SP, FileName}; -use syntax_pos::hygiene::ExpnFormat; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -189,10 +188,10 @@ impl AstFragmentKind { } } -fn macro_bang_format(path: &ast::Path) -> ExpnFormat { - // We don't want to format a path using pretty-printing, - // `format!("{}", path)`, because that tries to insert - // line-breaks and is slow. +// We don't want to format a path using pretty-printing, +// `format!("{}", path)`, because that tries to insert +// line-breaks and is slow. +fn fast_print_path(path: &ast::Path) -> String { let mut path_str = String::with_capacity(64); for (i, segment) in path.segments.iter().enumerate() { if i != 0 { @@ -202,8 +201,7 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat { path_str.push_str(&segment.ident.as_str()) } } - - MacroBang(Symbol::intern(&path_str)) + path_str } pub struct Invocation { @@ -388,8 +386,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { derives.push(mark); let item = match self.cx.resolver.resolve_macro_path( path, MacroKind::Derive, Mark::root(), Vec::new(), false) { - Ok(ext) => match *ext { - SyntaxExtension::LegacyDerive(..) => item_with_markers.clone(), + Ok(ext) => match ext.kind { + SyntaxExtensionKind::LegacyDerive(..) => item_with_markers.clone(), _ => item.clone(), }, _ => item.clone(), @@ -509,7 +507,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option { if invoc.fragment_kind == AstFragmentKind::ForeignItems && !self.cx.ecfg.macros_in_extern_enabled() { - if let SyntaxExtension::NonMacroAttr { .. } = *ext {} else { + if let SyntaxExtensionKind::NonMacroAttr { .. } = ext.kind {} else { emit_feature_err(&self.cx.parse_sess, sym::macros_in_extern, invoc.span(), GateIssue::Language, "macro invocations in `extern {}` blocks are experimental"); @@ -548,34 +546,25 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => unreachable!(), }; - if let SyntaxExtension::NonMacroAttr { mark_used: false } = *ext {} else { - // Macro attrs are always used when expanded, - // non-macro attrs are considered used when the field says so. - attr::mark_used(&attr); - } - invoc.expansion_data.mark.set_expn_info(ExpnInfo { - call_site: attr.span, - def_site: None, - format: MacroAttribute(Symbol::intern(&attr.path.to_string())), - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - edition: ext.edition(self.cx.parse_sess.edition), - }); + let expn_info = ext.expn_info(attr.span, &fast_print_path(&attr.path)); + invoc.expansion_data.mark.set_expn_info(expn_info); - match *ext { - SyntaxExtension::NonMacroAttr { .. } => { + match &ext.kind { + SyntaxExtensionKind::NonMacroAttr { mark_used } => { attr::mark_known(&attr); + if *mark_used { + attr::mark_used(&attr); + } item.visit_attrs(|attrs| attrs.push(attr)); Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item))) } - SyntaxExtension::LegacyAttr(ref mac) => { + SyntaxExtensionKind::LegacyAttr(expander) => { let meta = attr.parse_meta(self.cx.parse_sess) .map_err(|mut e| { e.emit(); }).ok()?; - let item = mac.expand(self.cx, attr.span, &meta, item); + let item = expander.expand(self.cx, attr.span, &meta, item); Some(invoc.fragment_kind.expect_from_annotatables(item)) } - SyntaxExtension::Attr(ref mac, ..) => { + SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_attr_item(attr.span, &item); let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item { Annotatable::Item(item) => token::NtItem(item), @@ -586,13 +575,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Annotatable::Expr(expr) => token::NtExpr(expr), })), DUMMY_SP).into(); let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span); - let tok_result = mac.expand(self.cx, attr.span, input, item_tok); + let tok_result = expander.expand(self.cx, attr.span, input, item_tok); let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind, &attr.path, attr.span); self.gate_proc_macro_expansion(attr.span, &res); res } - SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => { + SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => { self.cx.span_err(attr.span, &format!("`{}` is a derive macro", attr.path)); self.cx.trace_macros_diag(); invoc.fragment_kind.dummy(attr.span) @@ -701,21 +690,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let path = &mac.node.path; let ident = ident.unwrap_or_else(|| Ident::invalid()); - let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture - def_site_span: Option, - allow_internal_unstable, - allow_internal_unsafe, - local_inner_macros, - // can't infer this type - unstable_feature: Option<(Symbol, u32)>, - edition| { - + let validate_and_set_expn_info = |this: &mut Self| { // feature-gate the macro invocation - if let Some((feature, issue)) = unstable_feature { + if let Some((feature, issue)) = ext.unstable_feature { let crate_span = this.cx.current_expansion.crate_span.unwrap(); // don't stability-check macros in the same crate // (the only time this is null is for syntax extensions registered as macros) - if def_site_span.map_or(false, |def_span| !crate_span.contains(def_span)) + if ext.def_info.map_or(false, |(_, def_span)| !crate_span.contains(def_span)) && !span.allows_unstable(feature) && this.cx.ecfg.features.map_or(true, |feats| { // macro features will count as lib features @@ -734,62 +715,40 @@ impl<'a, 'b> MacroExpander<'a, 'b> { this.cx.trace_macros_diag(); return Err(kind.dummy(span)); } - mark.set_expn_info(ExpnInfo { - call_site: span, - def_site: def_site_span, - format: macro_bang_format(path), - allow_internal_unstable, - allow_internal_unsafe, - local_inner_macros, - edition, - }); + mark.set_expn_info(ext.expn_info(span, &fast_print_path(path))); Ok(()) }; - let opt_expanded = match *ext { - SyntaxExtension::LegacyBang { - ref expander, - def_info, - ref allow_internal_unstable, - allow_internal_unsafe, - local_inner_macros, - unstable_feature, - edition, - .. - } => { - if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s), - allow_internal_unstable.clone(), - allow_internal_unsafe, - local_inner_macros, - unstable_feature, - edition) { + let opt_expanded = match &ext.kind { + SyntaxExtensionKind::LegacyBang(expander) => { + if let Err(dummy_span) = validate_and_set_expn_info(self) { dummy_span } else { kind.make_from(expander.expand( self.cx, span, mac.node.stream(), - def_info.map(|(_, s)| s), + ext.def_info.map(|(_, s)| s), )) } } - SyntaxExtension::Attr(..) | - SyntaxExtension::LegacyAttr(..) | - SyntaxExtension::NonMacroAttr { .. } => { + SyntaxExtensionKind::Attr(..) | + SyntaxExtensionKind::LegacyAttr(..) | + SyntaxExtensionKind::NonMacroAttr { .. } => { self.cx.span_err(path.span, &format!("`{}` can only be used in attributes", path)); self.cx.trace_macros_diag(); kind.dummy(span) } - SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => { + SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => { self.cx.span_err(path.span, &format!("`{}` is a derive macro", path)); self.cx.trace_macros_diag(); kind.dummy(span) } - SyntaxExtension::Bang { ref expander, ref allow_internal_unstable, edition } => { + SyntaxExtensionKind::Bang(expander) => { if ident.name != kw::Invalid { let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident); @@ -798,19 +757,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { kind.dummy(span) } else { self.gate_proc_macro_expansion_kind(span, kind); - invoc.expansion_data.mark.set_expn_info(ExpnInfo { - call_site: span, - // FIXME procedural macros do not have proper span info - // yet, when they do, we should use it here. - def_site: None, - format: macro_bang_format(path), - // FIXME probably want to follow macro_rules macros here. - allow_internal_unstable: allow_internal_unstable.clone(), - allow_internal_unsafe: false, - local_inner_macros: false, - edition, - }); - + let expn_info = ext.expn_info(span, &fast_print_path(path)); + invoc.expansion_data.mark.set_expn_info(expn_info); let tok_result = expander.expand(self.cx, span, mac.node.stream()); let result = self.parse_ast_fragment(tok_result, kind, path, span); self.gate_proc_macro_expansion(span, &result); @@ -867,55 +815,23 @@ impl<'a, 'b> MacroExpander<'a, 'b> { return None; } - let pretty_name = Symbol::intern(&format!("derive({})", path)); - let span = path.span; - let attr = ast::Attribute { - path, span, - tokens: TokenStream::empty(), - // irrelevant: - id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false, - }; - - let mut expn_info = ExpnInfo { - call_site: span, - def_site: None, - format: MacroAttribute(pretty_name), - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - edition: ext.edition(self.cx.parse_sess.edition), - }; - - match ext { - SyntaxExtension::Derive(expander, ..) | SyntaxExtension::LegacyDerive(expander) => { - let meta = match ext { - SyntaxExtension::Derive(..) => ast::MetaItem { // FIXME(jseyfried) avoid this - path: Path::from_ident(Ident::invalid()), - span: DUMMY_SP, - node: ast::MetaItemKind::Word, - }, - _ => { - expn_info.allow_internal_unstable = Some(vec![ - sym::rustc_attrs, - Symbol::intern("derive_clone_copy"), - Symbol::intern("derive_eq"), - // RustcDeserialize and RustcSerialize - Symbol::intern("libstd_sys_internals"), - ].into()); - attr.meta()? - } - }; - + match &ext.kind { + SyntaxExtensionKind::Derive(expander) | + SyntaxExtensionKind::LegacyDerive(expander) => { + let expn_info = + ext.expn_info(path.span, &format!("derive({})", fast_print_path(&path))); invoc.expansion_data.mark.set_expn_info(expn_info); - let span = span.with_ctxt(self.cx.backtrace()); + + let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span: path.span, path }; + let span = meta.span.with_ctxt(self.cx.backtrace()); let items = expander.expand(self.cx, span, &meta, item); Some(invoc.fragment_kind.expect_from_annotatables(items)) } _ => { - let msg = &format!("macro `{}` may not be used for derive attributes", attr.path); - self.cx.span_err(span, msg); + let msg = &format!("macro `{}` may not be used for derive attributes", path); + self.cx.span_err(path.span, msg); self.cx.trace_macros_diag(); - invoc.fragment_kind.dummy(span) + invoc.fragment_kind.dummy(path.span) } } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 22745a1a76d53..7f051c260ec82 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -1,6 +1,7 @@ use crate::{ast, attr}; use crate::edition::Edition; -use crate::ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension, TTMacroExpander}; +use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind}; +use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; use crate::ext::expand::{AstFragment, AstFragmentKind}; use crate::ext::hygiene::Transparency; use crate::ext::tt::macro_parser::{Success, Error, Failure}; @@ -376,7 +377,7 @@ pub fn compile( valid, }); - let transparency = if attr::contains_name(&def.attrs, sym::rustc_transparent_macro) { + let default_transparency = if attr::contains_name(&def.attrs, sym::rustc_transparent_macro) { Transparency::Transparent } else if body.legacy { Transparency::SemiTransparent @@ -426,14 +427,15 @@ pub fn compile( } }); - SyntaxExtension::LegacyBang { - expander, + SyntaxExtension { + kind: SyntaxExtensionKind::LegacyBang(expander), def_info: Some((def.id, def.span)), - transparency, + default_transparency, allow_internal_unstable, allow_internal_unsafe, local_inner_macros, unstable_feature, + helper_attrs: Vec::new(), edition, } } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index eea94f0d19458..9072ad7b30fdf 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -20,7 +20,7 @@ fn ignored_span(sp: Span, edition: Edition) -> Span { call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("std_inject")), - allow_internal_unstable: Some(vec![sym::prelude_import].into()), + allow_internal_unstable: Some([sym::prelude_import][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition, diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index cbaf12529c101..0e1b10c14f17e 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -284,7 +284,7 @@ fn generate_test_harness(sess: &ParseSess, call_site: DUMMY_SP, def_site: None, format: MacroAttribute(sym::test_case), - allow_internal_unstable: Some(vec![sym::main, sym::test, sym::rustc_attrs].into()), + allow_internal_unstable: Some([sym::main, sym::test, sym::rustc_attrs][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: sess.edition, diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index cf54eacc3d46c..e4a413dda09c6 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -2,7 +2,9 @@ use rustc_data_structures::sync::Lrc; use syntax::ast::{self, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver, MultiItemModifier}; +use syntax::edition::Edition; +use syntax::ext::base::{Annotatable, ExtCtxt, Resolver, MultiItemModifier}; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::ext::build::AstBuilder; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ptr::P; @@ -67,11 +69,24 @@ macro_rules! derive_traits { } } - pub fn register_builtin_derives(resolver: &mut dyn Resolver) { + pub fn register_builtin_derives(resolver: &mut dyn Resolver, edition: Edition) { + let allow_internal_unstable = Some([ + sym::rustc_attrs, + Symbol::intern("derive_clone_copy"), + Symbol::intern("derive_eq"), + Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize + ][..].into()); + $( resolver.add_builtin( ast::Ident::with_empty_ctxt(Symbol::intern($name)), - Lrc::new(SyntaxExtension::LegacyDerive(Box::new(BuiltinDerive($func)))) + Lrc::new(SyntaxExtension { + allow_internal_unstable: allow_internal_unstable.clone(), + ..SyntaxExtension::default( + SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($func))), + edition, + ) + }), ); )* } diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 3dd17207cb8e9..d29d93a8678fb 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -43,32 +43,31 @@ pub mod proc_macro_impl; use rustc_data_structures::sync::Lrc; use syntax::ast; -use syntax::ext::base::{MacroExpanderFn, NamedSyntaxExtension, SyntaxExtension}; -use syntax::ext::hygiene::Transparency; +use syntax::ext::base::MacroExpanderFn; +use syntax::ext::base::{NamedSyntaxExtension, SyntaxExtension, SyntaxExtensionKind}; use syntax::edition::Edition; use syntax::symbol::{sym, Symbol}; pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, user_exts: Vec, edition: Edition) { - deriving::register_builtin_derives(resolver); + deriving::register_builtin_derives(resolver, edition); let mut register = |name, ext| { resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext)); }; macro_rules! register { ($( $name:ident: $f:expr, )*) => { $( - register(Symbol::intern(stringify!($name)), - SyntaxExtension::LegacyBang { - expander: Box::new($f as MacroExpanderFn), - def_info: None, - transparency: Transparency::SemiTransparent, - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - unstable_feature: None, - edition, - }); + register(Symbol::intern(stringify!($name)), SyntaxExtension::default( + SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition + )); + )* } + } + macro_rules! register_attr { + ($( $name:ident: $f:expr, )*) => { $( + register(Symbol::intern(stringify!($name)), SyntaxExtension::default( + SyntaxExtensionKind::LegacyAttr(Box::new($f)), edition + )); )* } } @@ -97,33 +96,25 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, assert: assert::expand_assert, } - register(sym::test_case, SyntaxExtension::LegacyAttr(Box::new(test_case::expand))); - register(sym::test, SyntaxExtension::LegacyAttr(Box::new(test::expand_test))); - register(sym::bench, SyntaxExtension::LegacyAttr(Box::new(test::expand_bench))); + register_attr! { + test_case: test_case::expand, + test: test::expand_test, + bench: test::expand_bench, + } // format_args uses `unstable` things internally. - register(Symbol::intern("format_args"), - SyntaxExtension::LegacyBang { - expander: Box::new(format::expand_format_args), - def_info: None, - transparency: Transparency::SemiTransparent, - allow_internal_unstable: Some(vec![sym::fmt_internals].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - unstable_feature: None, - edition, - }); - register(sym::format_args_nl, - SyntaxExtension::LegacyBang { - expander: Box::new(format::expand_format_args_nl), - def_info: None, - transparency: Transparency::SemiTransparent, - allow_internal_unstable: Some(vec![sym::fmt_internals].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - unstable_feature: None, - edition, - }); + register(Symbol::intern("format_args"), SyntaxExtension { + allow_internal_unstable: Some([sym::fmt_internals][..].into()), + ..SyntaxExtension::default( + SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args)), edition + ) + }); + register(sym::format_args_nl, SyntaxExtension { + allow_internal_unstable: Some([sym::fmt_internals][..].into()), + ..SyntaxExtension::default( + SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args_nl)), edition + ) + }); for (name, ext) in user_exts { register(name, ext); diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index 29297aa913ed4..cdef5c6a9f48b 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -351,10 +351,9 @@ fn mk_decls( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(sym::proc_macro), - allow_internal_unstable: Some(vec![ - sym::rustc_attrs, - Symbol::intern("proc_macro_internals"), - ].into()), + allow_internal_unstable: Some([ + sym::rustc_attrs, Symbol::intern("proc_macro_internals") + ][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: cx.parse_sess.edition, diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index c20dc6cb2d7cd..a8c8456a3bcf8 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -66,7 +66,7 @@ pub fn expand_test_or_bench( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(sym::test), - allow_internal_unstable: Some(vec![sym::rustc_attrs, sym::test].into()), + allow_internal_unstable: Some([sym::rustc_attrs, sym::test][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: cx.parse_sess.edition, diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs index cffecdd0f18e7..ce17cf2a6e789 100644 --- a/src/libsyntax_ext/test_case.rs +++ b/src/libsyntax_ext/test_case.rs @@ -41,7 +41,7 @@ pub fn expand( call_site: DUMMY_SP, def_site: None, format: MacroAttribute(sym::test_case), - allow_internal_unstable: Some(vec![sym::test, sym::rustc_attrs].into()), + allow_internal_unstable: Some([sym::test, sym::rustc_attrs][..].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: ecx.parse_sess.edition, diff --git a/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs b/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs index 330459fc08f55..4cf8a4e33c526 100644 --- a/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs +++ b/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs @@ -11,8 +11,8 @@ extern crate rustc_plugin; use std::borrow::ToOwned; use syntax::ast; use syntax::ext::build::AstBuilder; -use syntax::ext::base::{SyntaxExtension, TTMacroExpander, ExtCtxt, MacResult, MacEager}; -use syntax::ext::hygiene::Transparency; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; +use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager}; use syntax::print::pprust; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -38,15 +38,7 @@ impl TTMacroExpander for Expander { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { let args = reg.args().to_owned(); - reg.register_syntax_extension(Symbol::intern("plugin_args"), - SyntaxExtension::LegacyBang { - expander: Box::new(Expander { args: args, }), - def_info: None, - transparency: Transparency::SemiTransparent, - allow_internal_unstable: None, - allow_internal_unsafe: false, - local_inner_macros: false, - unstable_feature: None, - edition: reg.sess.edition(), - }); + reg.register_syntax_extension(Symbol::intern("plugin_args"), SyntaxExtension::default( + SyntaxExtensionKind::LegacyBang(Box::new(Expander { args })), reg.sess.edition() + )); } From 679000cc0e98b2810a2d1c76ae77ce2574a4ab91 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Jun 2019 00:31:46 +0300 Subject: [PATCH 2/8] allow_internal_unstable: Avoid some more allocations --- src/librustc/hir/lowering.rs | 15 ++++++++++----- src/libsyntax_ext/deriving/mod.rs | 19 +++---------------- src/libsyntax_ext/lib.rs | 5 +++-- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5a548ce8d9ff4..a491b1a099b8a 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -142,6 +142,9 @@ pub struct LoweringContext<'a> { current_hir_id_owner: Vec<(DefIndex, u32)>, item_local_id_counters: NodeMap, node_id_to_hir_id: IndexVec, + + allow_try_trait: Option>, + allow_gen_future: Option>, } pub trait Resolver { @@ -267,6 +270,8 @@ pub fn lower_crate( lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, in_scope_lifetimes: Vec::new(), + allow_try_trait: Some([sym::try_trait][..].into()), + allow_gen_future: Some([sym::gen_future][..].into()), }.lower_crate(krate) } @@ -1156,7 +1161,7 @@ impl<'a> LoweringContext<'a> { let unstable_span = self.mark_span_with_reason( CompilerDesugaringKind::Async, span, - Some(vec![sym::gen_future].into()), + self.allow_gen_future.clone(), ); let gen_future = self.expr_std_path( unstable_span, &[sym::future, sym::from_generator], None, ThinVec::new()); @@ -4382,7 +4387,7 @@ impl<'a> LoweringContext<'a> { let unstable_span = this.mark_span_with_reason( CompilerDesugaringKind::TryBlock, body.span, - Some(vec![sym::try_trait].into()), + this.allow_try_trait.clone(), ); let mut block = this.lower_block(body, true).into_inner(); let tail = block.expr.take().map_or_else( @@ -4968,13 +4973,13 @@ impl<'a> LoweringContext<'a> { let unstable_span = self.mark_span_with_reason( CompilerDesugaringKind::QuestionMark, e.span, - Some(vec![sym::try_trait].into()), + self.allow_try_trait.clone(), ); let try_span = self.sess.source_map().end_point(e.span); let try_span = self.mark_span_with_reason( CompilerDesugaringKind::QuestionMark, try_span, - Some(vec![sym::try_trait].into()), + self.allow_try_trait.clone(), ); // `Try::into_result()` @@ -5776,7 +5781,7 @@ impl<'a> LoweringContext<'a> { let gen_future_span = self.mark_span_with_reason( CompilerDesugaringKind::Await, await_span, - Some(vec![sym::gen_future].into()), + self.allow_gen_future.clone(), ); // let mut pinned = ; diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index e4a413dda09c6..1fe6094fca686 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -6,7 +6,6 @@ use syntax::edition::Edition; use syntax::ext::base::{Annotatable, ExtCtxt, Resolver, MultiItemModifier}; use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::ext::build::AstBuilder; -use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ptr::P; use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; @@ -71,6 +70,7 @@ macro_rules! derive_traits { pub fn register_builtin_derives(resolver: &mut dyn Resolver, edition: Edition) { let allow_internal_unstable = Some([ + sym::core_intrinsics, sym::rustc_attrs, Symbol::intern("derive_clone_copy"), Symbol::intern("derive_eq"), @@ -163,24 +163,11 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { /// Constructs an expression that calls an intrinsic fn call_intrinsic(cx: &ExtCtxt<'_>, - mut span: Span, + span: Span, intrinsic: &str, args: Vec>) -> P { - let intrinsic_allowed_via_allow_internal_unstable = cx - .current_expansion.mark.expn_info().unwrap() - .allow_internal_unstable.map_or(false, |features| features.iter().any(|&s| - s == sym::core_intrinsics - )); - if intrinsic_allowed_via_allow_internal_unstable { - span = span.with_ctxt(cx.backtrace()); - } else { // Avoid instability errors with user defined curstom derives, cc #36316 - let mut info = cx.current_expansion.mark.expn_info().unwrap(); - info.allow_internal_unstable = Some(vec![sym::core_intrinsics].into()); - let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(info); - span = span.with_ctxt(SyntaxContext::empty().apply_mark(mark)); - } + let span = span.with_ctxt(cx.backtrace()); let path = cx.std_path(&[sym::intrinsics, Symbol::intern(intrinsic)]); let call = cx.expr_call_global(span, path, args); diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index d29d93a8678fb..b868f5b273c4e 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -103,14 +103,15 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, } // format_args uses `unstable` things internally. + let allow_internal_unstable = Some([sym::fmt_internals][..].into()); register(Symbol::intern("format_args"), SyntaxExtension { - allow_internal_unstable: Some([sym::fmt_internals][..].into()), + allow_internal_unstable: allow_internal_unstable.clone(), ..SyntaxExtension::default( SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args)), edition ) }); register(sym::format_args_nl, SyntaxExtension { - allow_internal_unstable: Some([sym::fmt_internals][..].into()), + allow_internal_unstable, ..SyntaxExtension::default( SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args_nl)), edition ) From 085a8d03750b524a34bf14adc0c9a36a2503e016 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Jun 2019 11:10:48 +0300 Subject: [PATCH 3/8] syntax: Remove `DummyResolver` --- src/libsyntax/ext/base.rs | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 04cef0bba24bf..cc5a91465ae48 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -725,31 +725,6 @@ impl Determinacy { } } -pub struct DummyResolver; - -impl Resolver for DummyResolver { - fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID } - - fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() } - - fn resolve_dollar_crates(&mut self, _fragment: &AstFragment) {} - fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment, - _derives: &[Mark]) {} - fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc) {} - - fn resolve_imports(&mut self) {} - fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _invoc_id: Mark, _force: bool) - -> Result>, Determinacy> { - Err(Determinacy::Determined) - } - fn resolve_macro_path(&mut self, _path: &ast::Path, _kind: MacroKind, _invoc_id: Mark, - _derives_in_scope: Vec, _force: bool) - -> Result, Determinacy> { - Err(Determinacy::Determined) - } - fn check_unused_macros(&self) {} -} - #[derive(Clone)] pub struct ModuleData { pub mod_path: Vec, From 68e1141c45c71c56cc4904b72f2212701b5912d4 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Jun 2019 12:29:56 +0300 Subject: [PATCH 4/8] resolve: Avoid creating fresh syntax extensions for all non-macro attributes --- src/librustc_resolve/build_reduced_graph.rs | 10 +++------- src/librustc_resolve/lib.rs | 12 +++++++++++- src/librustc_resolve/macros.rs | 5 ++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index bb4edf355f8b5..60ffb0782f005 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -29,7 +29,7 @@ use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}; use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant}; -use syntax::ext::base::{MacroKind, SyntaxExtension, SyntaxExtensionKind}; +use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; @@ -772,12 +772,8 @@ impl<'a> Resolver<'a> { pub fn get_macro(&mut self, res: Res) -> Lrc { let def_id = match res { Res::Def(DefKind::Macro(..), def_id) => def_id, - Res::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::default( - SyntaxExtensionKind::NonMacroAttr { - mark_used: attr_kind == NonMacroAttrKind::Tool - }, - self.session.edition(), - )), + Res::NonMacroAttr(attr_kind) => + return self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool), _ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"), }; if let Some(ext) = self.macro_map.get(&def_id) { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 7f05e0f477c2d..dcc2a228b4a77 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -41,7 +41,7 @@ use rustc_metadata::cstore::CStore; use syntax::source_map::SourceMap; use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; -use syntax::ext::base::SyntaxExtension; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::base::MacroKind; use syntax::symbol::{Symbol, kw, sym}; @@ -1668,6 +1668,7 @@ pub struct Resolver<'a> { macro_use_prelude: FxHashMap>, pub all_macros: FxHashMap, macro_map: FxHashMap>, + non_macro_attrs: [Lrc; 2], macro_defs: FxHashMap, local_macro_def_scopes: FxHashMap>, @@ -1941,6 +1942,10 @@ impl<'a> Resolver<'a> { let mut macro_defs = FxHashMap::default(); macro_defs.insert(Mark::root(), root_def_id); + let non_macro_attr = |mark_used| Lrc::new(SyntaxExtension::default( + SyntaxExtensionKind::NonMacroAttr { mark_used }, session.edition() + )); + Resolver { session, @@ -2014,6 +2019,7 @@ impl<'a> Resolver<'a> { macro_use_prelude: FxHashMap::default(), all_macros: FxHashMap::default(), macro_map: FxHashMap::default(), + non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)], invocations, macro_defs, local_macro_def_scopes: FxHashMap::default(), @@ -2030,6 +2036,10 @@ impl<'a> Resolver<'a> { Default::default() } + fn non_macro_attr(&self, mark_used: bool) -> Lrc { + self.non_macro_attrs[mark_used as usize].clone() + } + /// Runs the function on each namespace. fn per_ns(&mut self, mut f: F) { f(self, TypeNS); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 89e28330be7e3..02342d212ebbd 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -15,7 +15,7 @@ use syntax::ast::{self, Ident}; use syntax::attr; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy}; -use syntax::ext::base::{MacroKind, SyntaxExtension, SyntaxExtensionKind}; +use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; @@ -211,8 +211,7 @@ impl<'a> base::Resolver for Resolver<'a> { Ok((res, ext)) => (res, ext), Err(Determinacy::Determined) if kind == MacroKind::Attr => { // Replace unresolved attributes with used inert attributes for better recovery. - let kind = SyntaxExtensionKind::NonMacroAttr { mark_used: true }; - return Ok(Some(Lrc::new(SyntaxExtension::default(kind, self.session.edition())))); + return Ok(Some(self.non_macro_attr(true))); } Err(determinacy) => return Err(determinacy), }; From 8ec502eecdccec643ae6631a323dc6f38b490269 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Jun 2019 22:18:56 +0300 Subject: [PATCH 5/8] syntax: Introduce `default`/`with_unstable` constructors for `ExpnInfo` --- src/librustc/hir/lowering.rs | 12 ++++-------- src/librustc_allocator/expand.rs | 21 +++++++-------------- src/libsyntax/ext/derive.rs | 13 ++++--------- src/libsyntax/std_inject.rs | 12 +++--------- src/libsyntax/test.rs | 13 ++++--------- src/libsyntax_ext/proc_macro_decls.rs | 15 ++++----------- src/libsyntax_ext/test.rs | 15 +++++---------- src/libsyntax_ext/test_case.rs | 15 +++++---------- src/libsyntax_pos/hygiene.rs | 23 +++++++++++++++++++++++ 9 files changed, 59 insertions(+), 80 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a491b1a099b8a..0edf407f7c9e3 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -62,14 +62,14 @@ use syntax::errors; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::print::pprust; use syntax::ptr::P; -use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned}; +use syntax::source_map::{self, respan, ExpnInfo, CompilerDesugaringKind, Spanned}; use syntax::source_map::CompilerDesugaringKind::IfTemporary; use syntax::std_inject; use syntax::symbol::{kw, sym, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::parse::token::{self, Token}; use syntax::visit::{self, Visitor}; -use syntax_pos::{DUMMY_SP, edition, Span}; +use syntax_pos::{DUMMY_SP, Span}; const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; @@ -853,14 +853,10 @@ impl<'a> LoweringContext<'a> { allow_internal_unstable: Option>, ) -> Span { let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(source_map::ExpnInfo { - call_site: span, + mark.set_expn_info(ExpnInfo { def_site: Some(span), - format: source_map::CompilerDesugaring(reason), allow_internal_unstable, - allow_internal_unsafe: false, - local_inner_macros: false, - edition: edition::Edition::from_session(), + ..ExpnInfo::default(source_map::CompilerDesugaring(reason), span, self.sess.edition()) }); span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) } diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index ecc165ca5ea9f..d402b0ddf6e85 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -19,7 +19,7 @@ use syntax::{ mut_visit::{self, MutVisitor}, parse::ParseSess, ptr::P, - symbol::{kw, sym, Symbol} + symbol::{kw, sym} }; use syntax_pos::Span; @@ -58,11 +58,10 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> { fn flat_map_item(&mut self, item: P) -> SmallVec<[P; 1]> { debug!("in submodule {}", self.in_submod); - let name = if attr::contains_name(&item.attrs, sym::global_allocator) { - "global_allocator" - } else { + if !attr::contains_name(&item.attrs, sym::global_allocator) { return mut_visit::noop_flat_map_item(item, self); - }; + } + match item.node { ItemKind::Static(..) => {} _ => { @@ -87,15 +86,9 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> { // Create a fresh Mark for the new macro expansion we are about to do let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo { - call_site: item.span, // use the call site of the static - def_site: None, - format: MacroAttribute(Symbol::intern(name)), - allow_internal_unstable: Some([sym::rustc_attrs][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: self.sess.edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(sym::global_allocator), item.span, self.sess.edition, &[sym::rustc_attrs] + )); // Tie the span to the macro expansion info we just created let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark)); diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 33620cb80f940..abc451c96ae0e 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -60,15 +60,10 @@ pub fn add_derived_markers(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P } pretty_name.push(')'); - cx.current_expansion.mark.set_expn_info(ExpnInfo { - call_site: span, - def_site: None, - format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), - allow_internal_unstable: Some([sym::rustc_attrs, sym::structural_match][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: cx.parse_sess.edition, - }); + cx.current_expansion.mark.set_expn_info(ExpnInfo::with_unstable( + ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), span, cx.parse_sess.edition, + &[sym::rustc_attrs, sym::structural_match], + )); let span = span.with_ctxt(cx.backtrace()); item.visit_attrs(|attrs| { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 9072ad7b30fdf..6630bf9081546 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -16,15 +16,9 @@ use syntax_pos::{DUMMY_SP, Span}; /// The expanded code uses the unstable `#[prelude_import]` attribute. fn ignored_span(sp: Span, edition: Edition) -> Span { let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo { - call_site: DUMMY_SP, - def_site: None, - format: MacroAttribute(Symbol::intern("std_inject")), - allow_internal_unstable: Some([sym::prelude_import][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(Symbol::intern("std_inject")), sp, edition, &[sym::prelude_import] + )); sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)) } diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 0e1b10c14f17e..f90b76721ee16 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -280,15 +280,10 @@ fn generate_test_harness(sess: &ParseSess, test_runner }; - mark.set_expn_info(ExpnInfo { - call_site: DUMMY_SP, - def_site: None, - format: MacroAttribute(sym::test_case), - allow_internal_unstable: Some([sym::main, sym::test, sym::rustc_attrs][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: sess.edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(sym::test_case), DUMMY_SP, sess.edition, + &[sym::main, sym::test, sym::rustc_attrs], + )); TestHarnessGenerator { cx, diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index cdef5c6a9f48b..45e65288a24ee 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -347,17 +347,10 @@ fn mk_decls( custom_macros: &[ProcMacroDef], ) -> P { let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo { - call_site: DUMMY_SP, - def_site: None, - format: MacroAttribute(sym::proc_macro), - allow_internal_unstable: Some([ - sym::rustc_attrs, Symbol::intern("proc_macro_internals") - ][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: cx.parse_sess.edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(sym::proc_macro), DUMMY_SP, cx.parse_sess.edition, + &[sym::rustc_attrs, Symbol::intern("proc_macro_internals")], + )); let span = DUMMY_SP.apply_mark(mark); let hidden = cx.meta_list_item_word(span, sym::hidden); diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index a8c8456a3bcf8..24d3055e71140 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -8,7 +8,7 @@ use syntax::attr; use syntax::ast; use syntax::print::pprust; use syntax::symbol::{Symbol, sym}; -use syntax_pos::{DUMMY_SP, Span}; +use syntax_pos::Span; use syntax::source_map::{ExpnInfo, MacroAttribute}; use std::iter; @@ -62,15 +62,10 @@ pub fn expand_test_or_bench( let (sp, attr_sp) = { let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo { - call_site: DUMMY_SP, - def_site: None, - format: MacroAttribute(sym::test), - allow_internal_unstable: Some([sym::rustc_attrs, sym::test][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: cx.parse_sess.edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(sym::test), attr_sp, cx.parse_sess.edition, + &[sym::rustc_attrs, sym::test], + )); (item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark)), attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))) }; diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs index ce17cf2a6e789..6e3bc05b65e4e 100644 --- a/src/libsyntax_ext/test_case.rs +++ b/src/libsyntax_ext/test_case.rs @@ -15,7 +15,7 @@ use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ast; use syntax::source_map::respan; use syntax::symbol::sym; -use syntax_pos::{DUMMY_SP, Span}; +use syntax_pos::Span; use syntax::source_map::{ExpnInfo, MacroAttribute}; use syntax::feature_gate; @@ -37,15 +37,10 @@ pub fn expand( let sp = { let mark = Mark::fresh(Mark::root()); - mark.set_expn_info(ExpnInfo { - call_site: DUMMY_SP, - def_site: None, - format: MacroAttribute(sym::test_case), - allow_internal_unstable: Some([sym::test, sym::rustc_attrs][..].into()), - allow_internal_unsafe: false, - local_inner_macros: false, - edition: ecx.parse_sess.edition, - }); + mark.set_expn_info(ExpnInfo::with_unstable( + MacroAttribute(sym::test_case), attr_sp, ecx.parse_sess.edition, + &[sym::test, sym::rustc_attrs], + )); attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)) }; diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index b827416ab53c2..e9a912ddbc237 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -682,6 +682,29 @@ pub struct ExpnInfo { pub edition: Edition, } +impl ExpnInfo { + /// Constructs an expansion info with default properties. + pub fn default(format: ExpnFormat, call_site: Span, edition: Edition) -> ExpnInfo { + ExpnInfo { + call_site, + def_site: None, + format, + allow_internal_unstable: None, + allow_internal_unsafe: false, + local_inner_macros: false, + edition, + } + } + + pub fn with_unstable(format: ExpnFormat, call_site: Span, edition: Edition, + allow_internal_unstable: &[Symbol]) -> ExpnInfo { + ExpnInfo { + allow_internal_unstable: Some(allow_internal_unstable.into()), + ..ExpnInfo::default(format, call_site, edition) + } + } +} + /// The source of expansion. #[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum ExpnFormat { From 2de2278f1a356cba63300cee0bca49ad8f4905ab Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Jun 2019 23:55:22 +0300 Subject: [PATCH 6/8] syntax: Move `default_transparency` into `ExpnInfo` --- src/librustc/ich/impls_syntax.rs | 9 ++++++- src/librustc_resolve/macros.rs | 1 - src/libsyntax/ext/base.rs | 3 ++- src/libsyntax_pos/hygiene.rs | 42 +++++++++++++------------------- 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 4f618457d6c6a..9430661f75ab7 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -391,10 +391,17 @@ impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind { NameValue(lit) }); +impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency { + Transparent, + SemiTransparent, + Opaque, +}); + impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo { call_site, - def_site, format, + def_site, + default_transparency, allow_internal_unstable, allow_internal_unsafe, local_inner_macros, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 02342d212ebbd..a7c98842fa3e3 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -226,7 +226,6 @@ impl<'a> base::Resolver for Resolver<'a> { self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id; self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark, normal_module_def_id); - invoc.expansion_data.mark.set_default_transparency(ext.default_transparency); } Ok(Some(ext)) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index cc5a91465ae48..e0fbdedd24bd7 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -680,8 +680,9 @@ impl SyntaxExtension { crate fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo { ExpnInfo { call_site, - def_site: self.def_info.map(|(_, span)| span), format: self.expn_format(Symbol::intern(format)), + def_site: self.def_info.map(|(_, span)| span), + default_transparency: self.default_transparency, allow_internal_unstable: self.allow_internal_unstable.clone(), allow_internal_unsafe: self.allow_internal_unsafe, local_inner_macros: self.local_inner_macros, diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index e9a912ddbc237..67b6e9da477f5 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -59,13 +59,12 @@ pub struct Mark(u32); #[derive(Clone, Debug)] struct MarkData { parent: Mark, - default_transparency: Transparency, expn_info: Option, } /// A property of a macro expansion that determines how identifiers /// produced by that expansion are resolved. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum Transparency { /// Identifier produced by a transparent expansion is always resolved at call-site. /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this. @@ -85,12 +84,7 @@ pub enum Transparency { impl Mark { pub fn fresh(parent: Mark) -> Self { HygieneData::with(|data| { - data.marks.push(MarkData { - parent, - // By default expansions behave like `macro_rules`. - default_transparency: Transparency::SemiTransparent, - expn_info: None, - }); + data.marks.push(MarkData { parent, expn_info: None }); Mark(data.marks.len() as u32 - 1) }) } @@ -126,12 +120,6 @@ impl Mark { HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info)) } - #[inline] - pub fn set_default_transparency(self, transparency: Transparency) { - assert_ne!(self, Mark::root()); - HygieneData::with(|data| data.marks[self.0 as usize].default_transparency = transparency) - } - pub fn is_descendant_of(self, ancestor: Mark) -> bool { HygieneData::with(|data| data.is_descendant_of(self, ancestor)) } @@ -172,9 +160,8 @@ impl Mark { #[inline] pub fn looks_like_proc_macro_derive(self) -> bool { HygieneData::with(|data| { - let mark_data = &data.marks[self.0 as usize]; - if mark_data.default_transparency == Transparency::Opaque { - if let Some(expn_info) = &mark_data.expn_info { + if data.default_transparency(self) == Transparency::Opaque { + if let Some(expn_info) = &data.marks[self.0 as usize].expn_info { if let ExpnFormat::MacroAttribute(name) = expn_info.format { if name.as_str().starts_with("derive(") { return true; @@ -199,9 +186,6 @@ impl HygieneData { HygieneData { marks: vec![MarkData { parent: Mark::root(), - // If the root is opaque, then loops searching for an opaque mark - // will automatically stop after reaching it. - default_transparency: Transparency::Opaque, expn_info: None, }], syntax_contexts: vec![SyntaxContextData { @@ -235,7 +219,9 @@ impl HygieneData { } fn default_transparency(&self, mark: Mark) -> Transparency { - self.marks[mark.0 as usize].default_transparency + self.marks[mark.0 as usize].expn_info.as_ref().map_or( + Transparency::SemiTransparent, |einfo| einfo.default_transparency + ) } fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext { @@ -427,7 +413,6 @@ impl SyntaxContext { HygieneData::with(|data| { data.marks.push(MarkData { parent: Mark::root(), - default_transparency: Transparency::SemiTransparent, expn_info: Some(expansion_info), }); @@ -651,6 +636,7 @@ impl fmt::Debug for SyntaxContext { /// Extra information for tracking spans of macro and syntax sugar expansion #[derive(Clone, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ExpnInfo { + // --- The part unique to each expansion. /// The location of the actual macro invocation or syntax sugar , e.g. /// `let x = foo!();` or `if let Some(y) = x {}` /// @@ -661,13 +647,18 @@ pub struct ExpnInfo { /// call_site span would have its own ExpnInfo, with the call_site /// pointing to the `foo!` invocation. pub call_site: Span, + /// The format with which the macro was invoked. + pub format: ExpnFormat, + + // --- The part specific to the macro/desugaring definition. + // --- FIXME: Share it between expansions with the same definition. /// The span of the macro definition itself. The macro may not /// have a sensible definition span (e.g., something defined /// completely inside libsyntax) in which case this is None. /// This span serves only informational purpose and is not used for resolution. pub def_site: Option, - /// The format with which the macro was invoked. - pub format: ExpnFormat, + /// Transparency used by `apply_mark` for mark with this expansion info by default. + pub default_transparency: Transparency, /// List of #[unstable]/feature-gated features that the macro is allowed to use /// internally without forcing the whole crate to opt-in /// to them. @@ -687,8 +678,9 @@ impl ExpnInfo { pub fn default(format: ExpnFormat, call_site: Span, edition: Edition) -> ExpnInfo { ExpnInfo { call_site, - def_site: None, format, + def_site: None, + default_transparency: Transparency::SemiTransparent, allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, From 1ff3bce5bbcf3f23ad90266f8f3de1ac13d23623 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 18 Jun 2019 01:36:44 +0300 Subject: [PATCH 7/8] hygiene: Avoid some unnecessary `ExpnInfo` clones --- src/libsyntax_pos/hygiene.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 67b6e9da477f5..4dbd4ccda910a 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -112,7 +112,7 @@ impl Mark { #[inline] pub fn expn_info(self) -> Option { - HygieneData::with(|data| data.expn_info(self)) + HygieneData::with(|data| data.expn_info(self).cloned()) } #[inline] @@ -204,8 +204,8 @@ impl HygieneData { GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut())) } - fn expn_info(&self, mark: Mark) -> Option { - self.marks[mark.0 as usize].expn_info.clone() + fn expn_info(&self, mark: Mark) -> Option<&ExpnInfo> { + self.marks[mark.0 as usize].expn_info.as_ref() } fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool { @@ -598,7 +598,7 @@ impl SyntaxContext { /// `ctxt.outer().expn_info()`. #[inline] pub fn outer_expn_info(self) -> Option { - HygieneData::with(|data| data.expn_info(data.outer(self))) + HygieneData::with(|data| data.expn_info(data.outer(self)).cloned()) } /// `ctxt.outer_and_expn_info()` is equivalent to but faster than @@ -607,7 +607,7 @@ impl SyntaxContext { pub fn outer_and_expn_info(self) -> (Mark, Option) { HygieneData::with(|data| { let outer = data.outer(self); - (outer, data.expn_info(outer)) + (outer, data.expn_info(outer).cloned()) }) } From e152554e11ff44b1a08e21a8416e1fc18504764e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 18 Jun 2019 10:48:44 +0300 Subject: [PATCH 8/8] resolve/expand: Move expansion info setting to a single earlier point --- src/librustc_resolve/macros.rs | 31 ++++++++++++++++++++++++++----- src/libsyntax/ext/base.rs | 2 +- src/libsyntax/ext/expand.rs | 32 +++----------------------------- 3 files changed, 30 insertions(+), 35 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index a7c98842fa3e3..d2fec0ed622d1 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -114,6 +114,22 @@ fn sub_namespace_match(candidate: Option, requirement: Option String { + let mut path_str = String::with_capacity(64); + for (i, segment) in path.segments.iter().enumerate() { + if i != 0 { + path_str.push_str("::"); + } + if segment.ident.name != kw::PathRoot { + path_str.push_str(&segment.ident.as_str()) + } + } + path_str +} + impl<'a> base::Resolver for Resolver<'a> { fn next_node_id(&mut self) -> ast::NodeId { self.session.next_node_id() @@ -209,14 +225,19 @@ impl<'a> base::Resolver for Resolver<'a> { let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope); let (res, ext) = match self.resolve_macro_to_res(path, kind, &parent_scope, true, force) { Ok((res, ext)) => (res, ext), - Err(Determinacy::Determined) if kind == MacroKind::Attr => { - // Replace unresolved attributes with used inert attributes for better recovery. - return Ok(Some(self.non_macro_attr(true))); - } + // Replace unresolved attributes with used inert attributes for better recovery. + Err(Determinacy::Determined) if kind == MacroKind::Attr => + (Res::Err, self.non_macro_attr(true)), Err(determinacy) => return Err(determinacy), }; - if let Res::Def(DefKind::Macro(_), def_id) = res { + let format = match kind { + MacroKind::Derive => format!("derive({})", fast_print_path(path)), + _ => fast_print_path(path), + }; + invoc.expansion_data.mark.set_expn_info(ext.expn_info(invoc.span(), &format)); + + if let Res::Def(_, def_id) = res { if after_derive { self.session.span_err(invoc.span(), "macro attributes must be placed before `#[derive]`"); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index e0fbdedd24bd7..318a5a3a82a2e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -677,7 +677,7 @@ impl SyntaxExtension { } } - crate fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo { + pub fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo { ExpnInfo { call_site, format: self.expn_format(Symbol::intern(format)), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 4e759c5e52865..7154cc409f268 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -188,22 +188,6 @@ impl AstFragmentKind { } } -// We don't want to format a path using pretty-printing, -// `format!("{}", path)`, because that tries to insert -// line-breaks and is slow. -fn fast_print_path(path: &ast::Path) -> String { - let mut path_str = String::with_capacity(64); - for (i, segment) in path.segments.iter().enumerate() { - if i != 0 { - path_str.push_str("::"); - } - if segment.ident.name != kw::PathRoot { - path_str.push_str(&segment.ident.as_str()) - } - } - path_str -} - pub struct Invocation { pub kind: InvocationKind, fragment_kind: AstFragmentKind, @@ -546,9 +530,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => unreachable!(), }; - let expn_info = ext.expn_info(attr.span, &fast_print_path(&attr.path)); - invoc.expansion_data.mark.set_expn_info(expn_info); - match &ext.kind { SyntaxExtensionKind::NonMacroAttr { mark_used } => { attr::mark_known(&attr); @@ -682,7 +663,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { invoc: Invocation, ext: &SyntaxExtension) -> Option { - let (mark, kind) = (invoc.expansion_data.mark, invoc.fragment_kind); + let kind = invoc.fragment_kind; let (mac, ident, span) = match invoc.kind { InvocationKind::Bang { mac, ident, span } => (mac, ident, span), _ => unreachable!(), @@ -690,7 +671,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let path = &mac.node.path; let ident = ident.unwrap_or_else(|| Ident::invalid()); - let validate_and_set_expn_info = |this: &mut Self| { + let validate = |this: &mut Self| { // feature-gate the macro invocation if let Some((feature, issue)) = ext.unstable_feature { let crate_span = this.cx.current_expansion.crate_span.unwrap(); @@ -715,13 +696,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { this.cx.trace_macros_diag(); return Err(kind.dummy(span)); } - mark.set_expn_info(ext.expn_info(span, &fast_print_path(path))); Ok(()) }; let opt_expanded = match &ext.kind { SyntaxExtensionKind::LegacyBang(expander) => { - if let Err(dummy_span) = validate_and_set_expn_info(self) { + if let Err(dummy_span) = validate(self) { dummy_span } else { kind.make_from(expander.expand( @@ -757,8 +737,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { kind.dummy(span) } else { self.gate_proc_macro_expansion_kind(span, kind); - let expn_info = ext.expn_info(span, &fast_print_path(path)); - invoc.expansion_data.mark.set_expn_info(expn_info); let tok_result = expander.expand(self.cx, span, mac.node.stream()); let result = self.parse_ast_fragment(tok_result, kind, path, span); self.gate_proc_macro_expansion(span, &result); @@ -818,10 +796,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { match &ext.kind { SyntaxExtensionKind::Derive(expander) | SyntaxExtensionKind::LegacyDerive(expander) => { - let expn_info = - ext.expn_info(path.span, &format!("derive({})", fast_print_path(&path))); - invoc.expansion_data.mark.set_expn_info(expn_info); - let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span: path.span, path }; let span = meta.span.with_ctxt(self.cx.backtrace()); let items = expander.expand(self.cx, span, &meta, item);