[[package]]
name = "rustc-ap-arena"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "rustc-ap-rustc_cratesio_shim"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "rustc-ap-rustc_data_structures"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "rustc-ap-rustc_errors"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-rustc_target"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "rustc-ap-serialize"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
[[package]]
name = "rustc-ap-syntax"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-syntax_pos"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rustc-ap-arena 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-arena 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
"checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb"
"checksum rustc-ap-arena 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e794b25832224eea9252ebfa9f94ab7070d0a60c977793112c611501cb56b48d"
-"checksum rustc-ap-arena 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83e91a01cd6c5a9e4f68c2b5c81b62b172aa9e00fc2fec862c0899e3fac1fd32"
+"checksum rustc-ap-arena 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f0687e373d86505f31faeaee87d2be552843a830a0a20e252e76337b9596161"
"checksum rustc-ap-rustc_cratesio_shim 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a78241b2ecb82ebb9221b4b7d37c024ff1f2e43f1b099f38a997f030fc7894b0"
-"checksum rustc-ap-rustc_cratesio_shim 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e8ea8fadc5d66c1527771816e83f7e7599543bd2e1583e279855370ab2f18e5"
+"checksum rustc-ap-rustc_cratesio_shim 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ab5b83e209f3bcdb3c058a996d54b67db58eed5496bd114a781d9faa021aba7"
"checksum rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5529c3927f32b0b56d1f6449a34f2218dc2160c6a6dde0cf47954d83a9a45764"
-"checksum rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "742ba74bc7d0f3ded56148329650f137fa5b90f7f0ecc4b4952150f32c66b147"
+"checksum rustc-ap-rustc_data_structures 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4bb330c149e9b133d4707718a7981d65ce4eb14f2d59cb487761aa922fefb206"
"checksum rustc-ap-rustc_errors 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1fef44a7d63f5d204c981adb26a14e85fe7ee5962050a4f664df6f425f9b48"
-"checksum rustc-ap-rustc_errors 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3714046c6f8c1c259822aefcca21b1862710a6cec24fd34c0796117f074c6769"
+"checksum rustc-ap-rustc_errors 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e19ae6a813d5cdd12b8b95cea71438bf8a5fa3505bea1e7d68d438a8ac5ae7b"
"checksum rustc-ap-rustc_target 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3939a9f7bf063536dd646894ca43b1378ec6a56ac5b2698cc6ba0b42bfadbdc"
-"checksum rustc-ap-rustc_target 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b982c4517c18080895b06149ce8aa8279fd013f629030bb7a179bfcff6d74ef2"
+"checksum rustc-ap-rustc_target 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "867d4a6bc1b62d373fc6ec72632d5cbd36f3cb1f4e51282d0c7b4e771b393031"
"checksum rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "692169d0bac8a4547f9778039460799e162664477a1eaec15d31507705f8c736"
-"checksum rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "27c7700595bff1a64ddb6f593c69db3f6d66b76b059b26137236c7e21e36db70"
+"checksum rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e095f23598f115432ffef263201e030626f454d183cf425ef68fcca984f6594b"
"checksum rustc-ap-syntax 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22e93ee3817b007d56b5c5b151e6cd7c7063455a1facaf9e0ca01f9d9365b716"
-"checksum rustc-ap-syntax 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6482d98c8be57d3cfe55dab744dd1a87f8462dc2ea0a8a4960f7bb1565be049"
+"checksum rustc-ap-syntax 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab8f97532dabc3713ac3e8d11a85f1a5b154486e79a0c2643d62078f0f948ce2"
"checksum rustc-ap-syntax_pos 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe5d24a137d6e202cd6eb96cb74f8cb4a2b257c42b74dd624e136b4e19f0a47d"
-"checksum rustc-ap-syntax_pos 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20af5e200b61a3e5ba4f58ed3cbd7593569faf8f0956d5233f4f27fee51b4c81"
+"checksum rustc-ap-syntax_pos 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e098adae207a4b8d470bc5e9565904cfe65dca799ba4c9efc872e7436eb5a67"
"checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
"checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
#![stable(feature = "rust1", since = "1.0.0")]
use iter::{FromIterator, FusedIterator, TrustedLen};
-use {mem, ops};
+use {hint, mem, ops};
use mem::PinMut;
// Note that this is not a lang item per se, but it has a hidden dependency on
match *self {
Some(ref mut v) => v,
- _ => unreachable!(),
+ None => unsafe { hint::unreachable_unchecked() },
}
}
match *self {
Some(ref mut v) => v,
- _ => unreachable!(),
+ None => unsafe { hint::unreachable_unchecked() },
}
}
_: ::syntax_pos::Span,
stream: tokenstream::TokenStream)
-> tokenstream::TokenStream {
- let mut info = cx.current_expansion.mark.expn_info().unwrap();
- info.callee.allow_internal_unstable = true;
- cx.current_expansion.mark.set_expn_info(info);
::__internal::set_sess(cx, || TokenStream(stream).quote().0)
}
}
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(codemap::ExpnInfo {
call_site: span,
- callee: codemap::NameAndSpan {
- format: codemap::CompilerDesugaring(reason),
- span: Some(span),
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: codemap::hygiene::default_edition(),
- },
+ def_site: Some(span),
+ format: codemap::CompilerDesugaring(reason),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: codemap::hygiene::default_edition(),
});
span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
}
node_to_def_index: NodeMap<DefIndex>,
def_index_to_node: [Vec<ast::NodeId>; 2],
pub(super) node_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
- macro_def_scopes: FxHashMap<Mark, DefId>,
- expansions: FxHashMap<DefIndex, Mark>,
+ /// If `Mark` is an ID of some macro expansion,
+ /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined.
+ parent_modules_of_macro_defs: FxHashMap<Mark, DefId>,
+ /// Item with a given `DefIndex` was defined during opaque macro expansion with ID `Mark`.
+ /// It can actually be defined during transparent macro expansions inside that opaque expansion,
+ /// but transparent expansions are ignored here.
+ opaque_expansions_that_defined: FxHashMap<DefIndex, Mark>,
next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>,
def_index_to_span: FxHashMap<DefIndex, Span>,
}
self.def_index_to_node[1].clone(),
],
node_to_hir_id: self.node_to_hir_id.clone(),
- macro_def_scopes: self.macro_def_scopes.clone(),
- expansions: self.expansions.clone(),
+ parent_modules_of_macro_defs: self.parent_modules_of_macro_defs.clone(),
+ opaque_expansions_that_defined: self.opaque_expansions_that_defined.clone(),
next_disambiguator: self.next_disambiguator.clone(),
def_index_to_span: self.def_index_to_span.clone(),
}
node_to_def_index: NodeMap(),
def_index_to_node: [vec![], vec![]],
node_to_hir_id: IndexVec::new(),
- macro_def_scopes: FxHashMap(),
- expansions: FxHashMap(),
+ parent_modules_of_macro_defs: FxHashMap(),
+ opaque_expansions_that_defined: FxHashMap(),
next_disambiguator: FxHashMap(),
def_index_to_span: FxHashMap(),
}
let expansion = expansion.modern();
if expansion != Mark::root() {
- self.expansions.insert(index, expansion);
+ self.opaque_expansions_that_defined.insert(index, expansion);
}
// The span is added if it isn't DUMMY_SP
self.node_to_hir_id = mapping;
}
- pub fn expansion(&self, index: DefIndex) -> Mark {
- self.expansions.get(&index).cloned().unwrap_or(Mark::root())
+ pub fn opaque_expansion_that_defined(&self, index: DefIndex) -> Mark {
+ self.opaque_expansions_that_defined.get(&index).cloned().unwrap_or(Mark::root())
}
- pub fn macro_def_scope(&self, mark: Mark) -> DefId {
- self.macro_def_scopes[&mark]
+ pub fn parent_module_of_macro_def(&self, mark: Mark) -> DefId {
+ self.parent_modules_of_macro_defs[&mark]
}
- pub fn add_macro_def_scope(&mut self, mark: Mark, scope: DefId) {
- self.macro_def_scopes.insert(mark, scope);
+ pub fn add_parent_module_of_macro_def(&mut self, mark: Mark, module: DefId) {
+ self.parent_modules_of_macro_defs.insert(mark, module);
}
}
impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
call_site,
- callee
-});
-
-impl_stable_hash_for!(struct ::syntax_pos::hygiene::NameAndSpan {
+ def_site,
format,
allow_internal_unstable,
allow_internal_unsafe,
- edition,
- span
+ edition
});
impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
}
if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
- let desugaring = k.as_symbol().as_str();
flags.push(("from_desugaring".to_string(), None));
- flags.push(("from_desugaring".to_string(), Some(desugaring.to_string())));
+ flags.push(("from_desugaring".to_string(), Some(k.name().to_string())));
}
let generics = self.tcx.generics_of(def_id);
let self_ty = trait_ref.self_ty();
}
pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) {
- let expansion = match scope.krate {
- LOCAL_CRATE => self.hir.definitions().expansion(scope.index),
+ ident = ident.modern();
+ let target_expansion = match scope.krate {
+ LOCAL_CRATE => self.hir.definitions().opaque_expansion_that_defined(scope.index),
_ => Mark::root(),
};
- ident = ident.modern();
- let scope = match ident.span.adjust(expansion) {
- Some(macro_def) => self.hir.definitions().macro_def_scope(macro_def),
+ let scope = match ident.span.adjust(target_expansion) {
+ Some(actual_expansion) =>
+ self.hir.definitions().parent_module_of_macro_def(actual_expansion),
None if block == DUMMY_NODE_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId
None => self.hir.get_module_parent(block),
};
use syntax::ast::{self, Expr, Ident, Item, ItemKind, TyKind, VisibilityKind};
use syntax::attr;
use syntax::codemap::respan;
-use syntax::codemap::{ExpnInfo, MacroAttribute, NameAndSpan};
+use syntax::codemap::{ExpnInfo, MacroAttribute};
use syntax::ext::base::ExtCtxt;
use syntax::ext::base::Resolver;
use syntax::ext::build::AstBuilder;
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo {
call_site: DUMMY_SP,
- callee: NameAndSpan {
- format: MacroAttribute(Symbol::intern(name)),
- span: None,
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- },
+ def_site: None,
+ format: MacroAttribute(Symbol::intern(name)),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
let ecfg = ExpansionConfig::default(name.to_string());
name: &str,
expand: fn(TokenStream) -> TokenStream) {
let expand = SyntaxExtension::ProcMacro(
- Box::new(BangProcMacro { inner: expand }), self.edition
+ Box::new(BangProcMacro { inner: expand }), false, self.edition
);
self.extensions.push((Symbol::intern(name), Lrc::new(expand)));
}
} else if data.name == "proc_macro" &&
self.get_crate_data(id.krate).item_name(id.index) == "quote" {
let ext = SyntaxExtension::ProcMacro(Box::new(::proc_macro::__internal::Quoter),
- data.root.edition);
+ true, data.root.edition);
return LoadedMacro::ProcMacro(Lrc::new(ext));
}
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
use syntax::codemap::CodeMap;
-use syntax::ext::hygiene::{Mark, MarkKind, SyntaxContext};
+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::Determinacy::{self, Determined, Undetermined};
// When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
// we don't want to pretend that the `macro_rules!` definition is in the `macro`
// as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
- ctxt.marks().into_iter().find(|&mark| mark.kind() != MarkKind::Modern)
+ ctxt.marks().into_iter().find(|&mark| mark.transparency() != Transparency::Opaque)
} else {
ctxt = ctxt.modern();
ctxt.adjust(Mark::root())
use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
-use syntax::ext::expand::{Expansion, ExpansionKind, Invocation, InvocationKind, find_attr_invoc};
-use syntax::ext::hygiene::{self, Mark, MarkKind};
+use syntax::ext::expand::{self, AstFragment, AstFragmentKind, Invocation, InvocationKind};
+use syntax::ext::hygiene::{self, Mark, Transparency};
use syntax::ext::placeholders::placeholder;
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{self, emit_feature_err, GateIssue};
self.whitelisted_legacy_custom_derives.contains(&name)
}
- fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]) {
+ fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
+ derives: &[Mark]) {
let invocation = self.invocations[&mark];
- self.collect_def_ids(mark, invocation, expansion);
+ self.collect_def_ids(mark, invocation, fragment);
self.current_module = invocation.module.get();
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
legacy_scope: LegacyScope::Invocation(invocation),
expansion: mark,
};
- expansion.visit_with(&mut visitor);
+ fragment.visit_with(&mut visitor);
invocation.expansion.set(visitor.legacy_scope);
}
self.macro_defs.insert(invoc.expansion_data.mark, def_id);
let normal_module_def_id =
self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
- self.definitions.add_macro_def_scope(invoc.expansion_data.mark, normal_module_def_id);
+ self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark,
+ normal_module_def_id);
self.unused_macros.remove(&def_id);
let ext = self.get_macro(def);
if ext.is_modern() {
- invoc.expansion_data.mark.set_kind(MarkKind::Modern);
+ invoc.expansion_data.mark.set_transparency(Transparency::Opaque);
} else if def_id.krate == BUILTIN_MACROS_CRATE {
- invoc.expansion_data.mark.set_kind(MarkKind::Builtin);
+ invoc.expansion_data.mark.set_is_builtin(true);
}
Ok(Some(ext))
}
Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext {
if inert_attrs.contains(&attr_name) {
// FIXME(jseyfried) Avoid `mem::replace` here.
- let dummy_item = placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID)
+ let dummy_item = placeholder(AstFragmentKind::Items, ast::DUMMY_NODE_ID)
.make_items().pop().unwrap();
let dummy_item = Annotatable::Item(dummy_item);
*item = mem::replace(item, dummy_item).map_attrs(|mut attrs| {
let inert_attr = attr.take().unwrap();
attr::mark_known(&inert_attr);
if self.proc_macro_enabled {
- *attr = find_attr_invoc(&mut attrs);
+ *attr = expand::find_attr_invoc(&mut attrs);
}
attrs.push(inert_attr);
attrs
fn collect_def_ids(&mut self,
mark: Mark,
invocation: &'a InvocationData<'a>,
- expansion: &Expansion) {
+ fragment: &AstFragment) {
let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
let InvocationData { def_index, .. } = *invocation;
let mut def_collector = DefCollector::new(&mut self.definitions, mark);
def_collector.visit_macro_invoc = Some(visit_macro_invoc);
def_collector.with_parent(def_index, |def_collector| {
- expansion.visit_with(def_collector)
+ fragment.visit_with(def_collector)
});
}
let callsite = span.source_callsite();
let callsite_span = self.span_from_span(callsite);
let callee = span.source_callee()?;
- let callee_span = callee.span?;
+ let callee_span = callee.def_site?;
// Ignore attribute macros, their spans are usually mangled
if let MacroAttribute(_) = callee.format {
let callee_span = self.span_from_span(callee_span);
Some(MacroRef {
span: callsite_span,
- qualname: callee.name().to_string(), // FIXME: generate the real qualname
+ qualname: callee.format.name().to_string(), // FIXME: generate the real qualname
callee_span,
})
}
pub use syntax_pos::*;
-pub use syntax_pos::hygiene::{ExpnFormat, ExpnInfo, NameAndSpan};
+pub use syntax_pos::hygiene::{ExpnFormat, ExpnInfo};
pub use self::ExpnFormat::*;
use rustc_data_structures::fx::FxHashMap;
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
use edition::Edition;
use errors::{DiagnosticBuilder, DiagnosticId};
-use ext::expand::{self, Expansion, Invocation};
+use ext::expand::{self, AstFragment, Invocation};
use ext::hygiene::{self, Mark, SyntaxContext};
use fold::{self, Folder};
use parse::{self, parser, DirectoryOwnership};
MultiModifier(Box<MultiItemModifier + sync::Sync + sync::Send>),
/// A function-like procedural macro. TokenStream -> TokenStream.
- ProcMacro(Box<ProcMacro + sync::Sync + sync::Send>, Edition),
+ ProcMacro(
+ /* expander: */ Box<ProcMacro + sync::Sync + sync::Send>,
+ /* allow_internal_unstable: */ bool,
+ /* edition: */ Edition,
+ ),
/// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
/// The first TokenSteam is the attribute, the second is the annotated item.
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool;
- fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]);
+ fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
+ derives: &[Mark]);
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
fn resolve_imports(&mut self);
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { 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_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment,
+ _derives: &[Mark]) {}
fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
fn resolve_imports(&mut self) {}
let mut last_macro = None;
loop {
if ctxt.outer().expn_info().map_or(None, |info| {
- if info.callee.name() == "include" {
+ if info.format.name() == "include" {
// Stop going up the backtrace once include! is encountered
return None;
}
use attr::HasAttrs;
use ast;
-use codemap::{hygiene, ExpnInfo, NameAndSpan, ExpnFormat};
+use codemap::{hygiene, ExpnInfo, ExpnFormat};
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use parse::parser::PathStyle;
cx.current_expansion.mark.set_expn_info(ExpnInfo {
call_site: span,
- callee: NameAndSpan {
- format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
- span: None,
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- },
+ def_site: None,
+ format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
let span = span.with_ctxt(cx.backtrace());
use ast::{self, Block, Ident, NodeId, PatKind, Path};
use ast::{MacStmtStyle, StmtKind, ItemKind};
use attr::{self, HasAttrs};
-use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute, dummy_spanned, respan};
+use codemap::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan};
use config::{is_test_or_bench, StripUnconfigured};
use errors::{Applicability, FatalError};
use ext::base::*;
use std::rc::Rc;
use std::path::PathBuf;
-macro_rules! expansions {
- ($($kind:ident: $ty:ty [$($vec:ident, $ty_elt:ty)*], $kind_name:expr, .$make:ident,
- $(.$fold:ident)* $(lift .$fold_elt:ident)*,
- $(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => {
+macro_rules! ast_fragments {
+ (
+ $($Kind:ident($AstTy:ty) {
+ $kind_name:expr;
+ $(one fn $fold_ast:ident; fn $visit_ast:ident;)?
+ $(many fn $fold_ast_elt:ident; fn $visit_ast_elt:ident;)?
+ fn $make_ast:ident;
+ })*
+ ) => {
+ /// A fragment of AST that can be produced by a single macro expansion.
+ /// Can also serve as an input and intermediate result for macro expansion operations.
+ pub enum AstFragment {
+ OptExpr(Option<P<ast::Expr>>),
+ $($Kind($AstTy),)*
+ }
+
+ /// "Discriminant" of an AST fragment.
#[derive(Copy, Clone, PartialEq, Eq)]
- pub enum ExpansionKind { OptExpr, $( $kind, )* }
- pub enum Expansion { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* }
+ pub enum AstFragmentKind {
+ OptExpr,
+ $($Kind,)*
+ }
- impl ExpansionKind {
+ impl AstFragmentKind {
pub fn name(self) -> &'static str {
match self {
- ExpansionKind::OptExpr => "expression",
- $( ExpansionKind::$kind => $kind_name, )*
+ AstFragmentKind::OptExpr => "expression",
+ $(AstFragmentKind::$Kind => $kind_name,)*
}
}
- fn make_from<'a>(self, result: Box<MacResult + 'a>) -> Option<Expansion> {
+ fn make_from<'a>(self, result: Box<MacResult + 'a>) -> Option<AstFragment> {
match self {
- ExpansionKind::OptExpr => result.make_expr().map(Some).map(Expansion::OptExpr),
- $( ExpansionKind::$kind => result.$make().map(Expansion::$kind), )*
+ AstFragmentKind::OptExpr =>
+ result.make_expr().map(Some).map(AstFragment::OptExpr),
+ $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
}
}
}
- impl Expansion {
+ impl AstFragment {
pub fn make_opt_expr(self) -> Option<P<ast::Expr>> {
match self {
- Expansion::OptExpr(expr) => expr,
- _ => panic!("Expansion::make_* called on the wrong kind of expansion"),
+ AstFragment::OptExpr(expr) => expr,
+ _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
}
}
- $( pub fn $make(self) -> $ty {
+
+ $(pub fn $make_ast(self) -> $AstTy {
match self {
- Expansion::$kind(ast) => ast,
- _ => panic!("Expansion::make_* called on the wrong kind of expansion"),
+ AstFragment::$Kind(ast) => ast,
+ _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
}
- } )*
+ })*
pub fn fold_with<F: Folder>(self, folder: &mut F) -> Self {
- use self::Expansion::*;
match self {
- OptExpr(expr) => OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))),
- $($( $kind(ast) => $kind(folder.$fold(ast)), )*)*
- $($( $kind(ast) => {
- $kind(ast.into_iter().flat_map(|ast| folder.$fold_elt(ast)).collect())
- }, )*)*
+ AstFragment::OptExpr(expr) =>
+ AstFragment::OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))),
+ $($(AstFragment::$Kind(ast) =>
+ AstFragment::$Kind(folder.$fold_ast(ast)),)?)*
+ $($(AstFragment::$Kind(ast) =>
+ AstFragment::$Kind(ast.into_iter()
+ .flat_map(|ast| folder.$fold_ast_elt(ast))
+ .collect()),)?)*
}
}
pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
match *self {
- Expansion::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
- Expansion::OptExpr(None) => {}
- $($( Expansion::$kind(ref ast) => visitor.$visit(ast), )*)*
- $($( Expansion::$kind(ref ast) => for ast in &ast[..] {
- visitor.$visit_elt(ast);
- }, )*)*
+ AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
+ AstFragment::OptExpr(None) => {}
+ $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
+ $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
+ visitor.$visit_ast_elt(ast_elt);
+ })?)*
}
}
}
impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
- self.expand(Expansion::OptExpr(Some(expr))).make_opt_expr()
+ self.expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr()
}
- $($(fn $fold(&mut self, node: $ty) -> $ty {
- self.expand(Expansion::$kind(node)).$make()
- })*)*
- $($(fn $fold_elt(&mut self, node: $ty_elt) -> $ty {
- self.expand(Expansion::$kind(SmallVector::one(node))).$make()
- })*)*
+ $($(fn $fold_ast(&mut self, ast: $AstTy) -> $AstTy {
+ self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()
+ })?)*
+ $($(fn $fold_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy {
+ self.expand_fragment(AstFragment::$Kind(SmallVector::one(ast_elt))).$make_ast()
+ })?)*
}
impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
- $(fn $make(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>) -> Option<$ty> {
- Some(self.make(ExpansionKind::$kind).$make())
+ $(fn $make_ast(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>)
+ -> Option<$AstTy> {
+ Some(self.make(AstFragmentKind::$Kind).$make_ast())
})*
}
}
}
-expansions! {
- Expr: P<ast::Expr> [], "expression", .make_expr, .fold_expr, .visit_expr;
- Pat: P<ast::Pat> [], "pattern", .make_pat, .fold_pat, .visit_pat;
- Ty: P<ast::Ty> [], "type", .make_ty, .fold_ty, .visit_ty;
- Stmts: SmallVector<ast::Stmt> [SmallVector, ast::Stmt],
- "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt;
- Items: SmallVector<P<ast::Item>> [SmallVector, P<ast::Item>],
- "item", .make_items, lift .fold_item, lift .visit_item;
- TraitItems: SmallVector<ast::TraitItem> [SmallVector, ast::TraitItem],
- "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item;
- ImplItems: SmallVector<ast::ImplItem> [SmallVector, ast::ImplItem],
- "impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item;
- ForeignItems: SmallVector<ast::ForeignItem> [SmallVector, ast::ForeignItem],
- "foreign item", .make_foreign_items, lift .fold_foreign_item, lift .visit_foreign_item;
+ast_fragments! {
+ Expr(P<ast::Expr>) { "expression"; one fn fold_expr; fn visit_expr; fn make_expr; }
+ Pat(P<ast::Pat>) { "pattern"; one fn fold_pat; fn visit_pat; fn make_pat; }
+ Ty(P<ast::Ty>) { "type"; one fn fold_ty; fn visit_ty; fn make_ty; }
+ Stmts(SmallVector<ast::Stmt>) { "statement"; many fn fold_stmt; fn visit_stmt; fn make_stmts; }
+ Items(SmallVector<P<ast::Item>>) { "item"; many fn fold_item; fn visit_item; fn make_items; }
+ TraitItems(SmallVector<ast::TraitItem>) {
+ "trait item"; many fn fold_trait_item; fn visit_trait_item; fn make_trait_items;
+ }
+ ImplItems(SmallVector<ast::ImplItem>) {
+ "impl item"; many fn fold_impl_item; fn visit_impl_item; fn make_impl_items;
+ }
+ ForeignItems(SmallVector<ast::ForeignItem>) {
+ "foreign item"; many fn fold_foreign_item; fn visit_foreign_item; fn make_foreign_items;
+ }
}
-impl ExpansionKind {
- fn dummy(self, span: Span) -> Option<Expansion> {
+impl AstFragmentKind {
+ fn dummy(self, span: Span) -> Option<AstFragment> {
self.make_from(DummyResult::any(span))
}
- fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I) -> Expansion {
+ fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I)
+ -> AstFragment {
let mut items = items.into_iter();
match self {
- ExpansionKind::Items =>
- Expansion::Items(items.map(Annotatable::expect_item).collect()),
- ExpansionKind::ImplItems =>
- Expansion::ImplItems(items.map(Annotatable::expect_impl_item).collect()),
- ExpansionKind::TraitItems =>
- Expansion::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
- ExpansionKind::ForeignItems =>
- Expansion::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()),
- ExpansionKind::Stmts => Expansion::Stmts(items.map(Annotatable::expect_stmt).collect()),
- ExpansionKind::Expr => Expansion::Expr(
+ AstFragmentKind::Items =>
+ AstFragment::Items(items.map(Annotatable::expect_item).collect()),
+ AstFragmentKind::ImplItems =>
+ AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect()),
+ AstFragmentKind::TraitItems =>
+ AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
+ AstFragmentKind::ForeignItems =>
+ AstFragment::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()),
+ AstFragmentKind::Stmts =>
+ AstFragment::Stmts(items.map(Annotatable::expect_stmt).collect()),
+ AstFragmentKind::Expr => AstFragment::Expr(
items.next().expect("expected exactly one expression").expect_expr()
),
- ExpansionKind::OptExpr =>
- Expansion::OptExpr(items.next().map(Annotatable::expect_expr)),
- ExpansionKind::Pat | ExpansionKind::Ty =>
+ AstFragmentKind::OptExpr =>
+ AstFragment::OptExpr(items.next().map(Annotatable::expect_expr)),
+ AstFragmentKind::Pat | AstFragmentKind::Ty =>
panic!("patterns and types aren't annotatable"),
}
}
pub struct Invocation {
pub kind: InvocationKind,
- expansion_kind: ExpansionKind,
+ fragment_kind: AstFragmentKind,
pub expansion_data: ExpansionData,
}
let orig_mod_span = krate.module.inner;
- let krate_item = Expansion::Items(SmallVector::one(P(ast::Item {
+ let krate_item = AstFragment::Items(SmallVector::one(P(ast::Item {
attrs: krate.attrs,
span: krate.span,
node: ast::ItemKind::Mod(krate.module),
tokens: None,
})));
- match self.expand(krate_item).make_items().pop().map(P::into_inner) {
+ match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
krate.attrs = attrs;
krate.module = module;
krate
}
- // Fully expand all the invocations in `expansion`.
- fn expand(&mut self, expansion: Expansion) -> Expansion {
+ // Fully expand all macro invocations in this AST fragment.
+ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
let orig_expansion_data = self.cx.current_expansion.clone();
self.cx.current_expansion.depth = 0;
- let (expansion, mut invocations) = self.collect_invocations(expansion, &[]);
+ // Collect all macro invocations and replace them with placeholders.
+ let (fragment_with_placeholders, mut invocations)
+ = self.collect_invocations(input_fragment, &[]);
+
+ // Optimization: if we resolve all imports now,
+ // we'll be able to immediately resolve most of imported macros.
self.resolve_imports();
- invocations.reverse();
- let mut expansions = Vec::new();
+ // Resolve paths in all invocations and produce ouput expanded fragments for them, but
+ // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
+ // The output fragments also go through expansion recursively until no invocations are left.
+ // Unresolved macros produce dummy outputs as a recovery measure.
+ invocations.reverse();
+ let mut expanded_fragments = Vec::new();
let mut derives = HashMap::new();
let mut undetermined_invocations = Vec::new();
let (mut progress, mut force) = (false, !self.monotonic);
self.cx.current_expansion.mark = scope;
// FIXME(jseyfried): Refactor out the following logic
- let (expansion, new_invocations) = if let Some(ext) = ext {
+ let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
if let Some(ext) = ext {
- let dummy = invoc.expansion_kind.dummy(invoc.span()).unwrap();
- let expansion = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
- self.collect_invocations(expansion, &[])
+ let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap();
+ let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
+ self.collect_invocations(fragment, &[])
} else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
if !item.derive_allowed() {
let attr = attr::find_by_name(item.attrs(), "derive")
};
invocations.push(Invocation {
kind: InvocationKind::Derive { path: path.clone(), item: item },
- expansion_kind: invoc.expansion_kind,
+ fragment_kind: invoc.fragment_kind,
expansion_data: ExpansionData {
mark,
..invoc.expansion_data.clone()
},
});
}
- let expansion = invoc.expansion_kind
+ let fragment = invoc.fragment_kind
.expect_from_annotatables(::std::iter::once(item_with_markers));
- self.collect_invocations(expansion, derives)
+ self.collect_invocations(fragment, derives)
} else {
unreachable!()
}
} else {
- self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()).unwrap(), &[])
+ self.collect_invocations(invoc.fragment_kind.dummy(invoc.span()).unwrap(), &[])
};
- if expansions.len() < depth {
- expansions.push(Vec::new());
+ if expanded_fragments.len() < depth {
+ expanded_fragments.push(Vec::new());
}
- expansions[depth - 1].push((mark, expansion));
+ expanded_fragments[depth - 1].push((mark, expanded_fragment));
if !self.cx.ecfg.single_step {
invocations.extend(new_invocations.into_iter().rev());
}
self.cx.current_expansion = orig_expansion_data;
+ // Finally incorporate all the expanded macros into the input AST fragment.
let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
- while let Some(expansions) = expansions.pop() {
- for (mark, expansion) in expansions.into_iter().rev() {
+ while let Some(expanded_fragments) = expanded_fragments.pop() {
+ for (mark, expanded_fragment) in expanded_fragments.into_iter().rev() {
let derives = derives.remove(&mark).unwrap_or_else(Vec::new);
- placeholder_expander.add(NodeId::placeholder_from_mark(mark), expansion, derives);
+ placeholder_expander.add(NodeId::placeholder_from_mark(mark),
+ expanded_fragment, derives);
}
}
-
- expansion.fold_with(&mut placeholder_expander)
+ fragment_with_placeholders.fold_with(&mut placeholder_expander)
}
fn resolve_imports(&mut self) {
}
}
- fn collect_invocations(&mut self, expansion: Expansion, derives: &[Mark])
- -> (Expansion, Vec<Invocation>) {
- let result = {
+ /// Collect all macro invocations reachable at this time in this AST fragment, and replace
+ /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
+ /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
+ /// prepares data for resolving paths of macro invocations.
+ fn collect_invocations(&mut self, fragment: AstFragment, derives: &[Mark])
+ -> (AstFragment, Vec<Invocation>) {
+ let (fragment_with_placeholders, invocations) = {
let mut collector = InvocationCollector {
cfg: StripUnconfigured {
should_test: self.cx.ecfg.should_test,
invocations: Vec::new(),
monotonic: self.monotonic,
};
- (expansion.fold_with(&mut collector), collector.invocations)
+ (fragment.fold_with(&mut collector), collector.invocations)
};
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_ast_fragment_with_placeholders(mark, &fragment_with_placeholders,
+ derives);
self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
}
- result
+ (fragment_with_placeholders, invocations)
}
fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
}
}
- fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<Expansion> {
+ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<AstFragment> {
let result = match invoc.kind {
InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?,
InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?,
let suggested_limit = self.cx.ecfg.recursion_limit * 2;
let mut err = self.cx.struct_span_err(info.call_site,
&format!("recursion limit reached while expanding the macro `{}`",
- info.callee.name()));
+ info.format.name()));
err.help(&format!(
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
suggested_limit));
fn expand_attr_invoc(&mut self,
invoc: Invocation,
ext: &SyntaxExtension)
- -> Option<Expansion> {
- let Invocation { expansion_kind: kind, .. } = invoc;
+ -> Option<AstFragment> {
let (attr, item) = match invoc.kind {
InvocationKind::Attr { attr, item, .. } => (attr?, item),
_ => unreachable!(),
attr::mark_used(&attr);
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
call_site: attr.span,
- callee: NameAndSpan {
- format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
- span: None,
- allow_internal_unstable: false,
- allow_internal_unsafe: false,
- edition: ext.edition(),
- }
+ def_site: None,
+ format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
+ allow_internal_unstable: false,
+ allow_internal_unsafe: false,
+ edition: ext.edition(),
});
match *ext {
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);
- Some(kind.expect_from_annotatables(item))
+ Some(invoc.fragment_kind.expect_from_annotatables(item))
}
MultiDecorator(ref mac) => {
let mut items = Vec::new();
.expect("derive meta should already have been parsed");
mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item));
items.push(item);
- Some(kind.expect_from_annotatables(items))
+ Some(invoc.fragment_kind.expect_from_annotatables(items))
}
AttrProcMacro(ref mac, ..) => {
self.gate_proc_macro_attr_item(attr.span, &item);
})).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 res = self.parse_expansion(tok_result, kind, &attr.path, attr.span);
+ let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind,
+ &attr.path, attr.span);
self.gate_proc_macro_expansion(attr.span, &res);
res
}
ProcMacroDerive(..) | BuiltinDerive(..) => {
self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path));
self.cx.trace_macros_diag();
- kind.dummy(attr.span)
+ invoc.fragment_kind.dummy(attr.span)
}
_ => {
let msg = &format!("macro `{}` may not be used in attributes", attr.path);
self.cx.span_err(attr.span, msg);
self.cx.trace_macros_diag();
- kind.dummy(attr.span)
+ invoc.fragment_kind.dummy(attr.span)
}
}
}
);
}
- fn gate_proc_macro_expansion(&self, span: Span, expansion: &Option<Expansion>) {
+ fn gate_proc_macro_expansion(&self, span: Span, fragment: &Option<AstFragment>) {
if self.cx.ecfg.proc_macro_gen() {
return
}
- let expansion = match expansion {
- Some(expansion) => expansion,
+ let fragment = match fragment {
+ Some(fragment) => fragment,
None => return,
};
- expansion.visit_with(&mut DisallowModules {
+ fragment.visit_with(&mut DisallowModules {
span,
parse_sess: self.cx.parse_sess,
});
}
}
- /// Expand a macro invocation. Returns the result of expansion.
+ /// Expand a macro invocation. Returns the resulting expanded AST fragment.
fn expand_bang_invoc(&mut self,
invoc: Invocation,
ext: &SyntaxExtension)
- -> Option<Expansion> {
- let (mark, kind) = (invoc.expansion_data.mark, invoc.expansion_kind);
+ -> Option<AstFragment> {
+ let (mark, kind) = (invoc.expansion_data.mark, invoc.fragment_kind);
let (mac, ident, span) = match invoc.kind {
InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
_ => unreachable!(),
}
mark.set_expn_info(ExpnInfo {
call_site: span,
- callee: NameAndSpan {
- format: macro_bang_format(path),
- span: def_site_span,
- allow_internal_unstable,
- allow_internal_unsafe,
- edition,
- },
+ def_site: def_site_span,
+ format: macro_bang_format(path),
+ allow_internal_unstable,
+ allow_internal_unsafe,
+ edition,
});
Ok(())
};
} else {
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
call_site: span,
- callee: NameAndSpan {
- format: macro_bang_format(path),
- span: tt_span,
- allow_internal_unstable,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- }
+ def_site: tt_span,
+ format: macro_bang_format(path),
+ allow_internal_unstable,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
let input: Vec<_> = mac.node.stream().into_trees().collect();
kind.dummy(span)
}
- ProcMacro(ref expandfun, edition) => {
+ ProcMacro(ref expandfun, allow_internal_unstable, edition) => {
if ident.name != keywords::Invalid.name() {
let msg =
format!("macro {}! expects no ident argument, given '{}'", path, ident);
self.gate_proc_macro_expansion_kind(span, kind);
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
call_site: span,
- callee: NameAndSpan {
- format: macro_bang_format(path),
- // FIXME procedural macros do not have proper span info
- // yet, when they do, we should use it here.
- span: None,
- // FIXME probably want to follow macro_rules macros here.
- allow_internal_unstable: false,
- allow_internal_unsafe: false,
- edition,
- },
+ // 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_unsafe: false,
+ edition,
});
let tok_result = expandfun.expand(self.cx, span, mac.node.stream());
- let result = self.parse_expansion(tok_result, kind, path, span);
+ let result = self.parse_ast_fragment(tok_result, kind, path, span);
self.gate_proc_macro_expansion(span, &result);
result
}
}
}
- fn gate_proc_macro_expansion_kind(&self, span: Span, kind: ExpansionKind) {
+ fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
let kind = match kind {
- ExpansionKind::Expr => "expressions",
- ExpansionKind::OptExpr => "expressions",
- ExpansionKind::Pat => "patterns",
- ExpansionKind::Ty => "types",
- ExpansionKind::Stmts => "statements",
- ExpansionKind::Items => return,
- ExpansionKind::TraitItems => return,
- ExpansionKind::ImplItems => return,
- ExpansionKind::ForeignItems => return,
+ AstFragmentKind::Expr => "expressions",
+ AstFragmentKind::OptExpr => "expressions",
+ AstFragmentKind::Pat => "patterns",
+ AstFragmentKind::Ty => "types",
+ AstFragmentKind::Stmts => "statements",
+ AstFragmentKind::Items => return,
+ AstFragmentKind::TraitItems => return,
+ AstFragmentKind::ImplItems => return,
+ AstFragmentKind::ForeignItems => return,
};
if self.cx.ecfg.proc_macro_non_items() {
return
);
}
- /// Expand a derive invocation. Returns the result of expansion.
+ /// Expand a derive invocation. Returns the resulting expanded AST fragment.
fn expand_derive_invoc(&mut self,
invoc: Invocation,
ext: &SyntaxExtension)
- -> Option<Expansion> {
- let Invocation { expansion_kind: kind, .. } = invoc;
+ -> Option<AstFragment> {
let (path, item) = match invoc.kind {
InvocationKind::Derive { path, item } => (path, item),
_ => unreachable!(),
let mut expn_info = ExpnInfo {
call_site: span,
- callee: NameAndSpan {
- format: MacroAttribute(pretty_name),
- span: None,
- allow_internal_unstable: false,
- allow_internal_unsafe: false,
- edition: ext.edition(),
- }
+ def_site: None,
+ format: MacroAttribute(pretty_name),
+ allow_internal_unstable: false,
+ allow_internal_unsafe: false,
+ edition: ext.edition(),
};
match *ext {
node: ast::MetaItemKind::Word,
};
let items = ext.expand(self.cx, span, &dummy, item);
- Some(kind.expect_from_annotatables(items))
+ Some(invoc.fragment_kind.expect_from_annotatables(items))
}
BuiltinDerive(func) => {
- expn_info.callee.allow_internal_unstable = true;
+ expn_info.allow_internal_unstable = true;
invoc.expansion_data.mark.set_expn_info(expn_info);
let span = span.with_ctxt(self.cx.backtrace());
let mut items = Vec::new();
func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a));
- Some(kind.expect_from_annotatables(items))
+ 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);
self.cx.trace_macros_diag();
- kind.dummy(span)
+ invoc.fragment_kind.dummy(span)
}
}
}
- fn parse_expansion(&mut self,
- toks: TokenStream,
- kind: ExpansionKind,
- path: &Path,
- span: Span)
- -> Option<Expansion> {
+ fn parse_ast_fragment(&mut self,
+ toks: TokenStream,
+ kind: AstFragmentKind,
+ path: &Path,
+ span: Span)
+ -> Option<AstFragment> {
let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
- match parser.parse_expansion(kind, false) {
- Ok(expansion) => {
+ match parser.parse_ast_fragment(kind, false) {
+ Ok(fragment) => {
parser.ensure_complete_parse(path, kind.name(), span);
- Some(expansion)
+ Some(fragment)
}
Err(mut err) => {
err.set_span(span);
}
impl<'a> Parser<'a> {
- pub fn parse_expansion(&mut self, kind: ExpansionKind, macro_legacy_warnings: bool)
- -> PResult<'a, Expansion> {
+ pub fn parse_ast_fragment(&mut self, kind: AstFragmentKind, macro_legacy_warnings: bool)
+ -> PResult<'a, AstFragment> {
Ok(match kind {
- ExpansionKind::Items => {
+ AstFragmentKind::Items => {
let mut items = SmallVector::new();
while let Some(item) = self.parse_item()? {
items.push(item);
}
- Expansion::Items(items)
+ AstFragment::Items(items)
}
- ExpansionKind::TraitItems => {
+ AstFragmentKind::TraitItems => {
let mut items = SmallVector::new();
while self.token != token::Eof {
items.push(self.parse_trait_item(&mut false)?);
}
- Expansion::TraitItems(items)
+ AstFragment::TraitItems(items)
}
- ExpansionKind::ImplItems => {
+ AstFragmentKind::ImplItems => {
let mut items = SmallVector::new();
while self.token != token::Eof {
items.push(self.parse_impl_item(&mut false)?);
}
- Expansion::ImplItems(items)
+ AstFragment::ImplItems(items)
}
- ExpansionKind::ForeignItems => {
+ AstFragmentKind::ForeignItems => {
let mut items = SmallVector::new();
while self.token != token::Eof {
if let Some(item) = self.parse_foreign_item()? {
items.push(item);
}
}
- Expansion::ForeignItems(items)
+ AstFragment::ForeignItems(items)
}
- ExpansionKind::Stmts => {
+ AstFragmentKind::Stmts => {
let mut stmts = SmallVector::new();
while self.token != token::Eof &&
// won't make progress on a `}`
stmts.push(stmt);
}
}
- Expansion::Stmts(stmts)
+ AstFragment::Stmts(stmts)
}
- ExpansionKind::Expr => Expansion::Expr(self.parse_expr()?),
- ExpansionKind::OptExpr => {
+ AstFragmentKind::Expr => AstFragment::Expr(self.parse_expr()?),
+ AstFragmentKind::OptExpr => {
if self.token != token::Eof {
- Expansion::OptExpr(Some(self.parse_expr()?))
+ AstFragment::OptExpr(Some(self.parse_expr()?))
} else {
- Expansion::OptExpr(None)
+ AstFragment::OptExpr(None)
}
},
- ExpansionKind::Ty => Expansion::Ty(self.parse_ty()?),
- ExpansionKind::Pat => Expansion::Pat(self.parse_pat()?),
+ AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?),
+ AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat()?),
})
}
}
impl<'a, 'b> InvocationCollector<'a, 'b> {
- fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
+ fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
let mark = Mark::fresh(self.cx.current_expansion.mark);
self.invocations.push(Invocation {
kind,
- expansion_kind,
+ fragment_kind,
expansion_data: ExpansionData {
mark,
depth: self.cx.current_expansion.depth + 1,
..self.cx.current_expansion.clone()
},
});
- placeholder(expansion_kind, NodeId::placeholder_from_mark(mark))
+ placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
}
- fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: ExpansionKind) -> Expansion {
+ fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
}
attr: Option<ast::Attribute>,
traits: Vec<Path>,
item: Annotatable,
- kind: ExpansionKind)
- -> Expansion {
+ kind: AstFragmentKind)
+ -> AstFragment {
self.collect(kind, InvocationKind::Attr { attr, traits, item })
}
// expansion will eat the attribute so it won't error later
attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
- // ExpansionKind::Expr requires the macro to emit an expression
- return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), ExpansionKind::Expr)
- .make_expr();
+ // AstFragmentKind::Expr requires the macro to emit an expression
+ return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
+ AstFragmentKind::Expr).make_expr();
}
if let ast::ExprKind::Mac(mac) = expr.node {
self.check_attributes(&expr.attrs);
- self.collect_bang(mac, expr.span, ExpansionKind::Expr).make_expr()
+ self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr()
} else {
P(noop_fold_expr(expr, self))
}
attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
- ExpansionKind::OptExpr)
+ AstFragmentKind::OptExpr)
.make_opt_expr();
}
if let ast::ExprKind::Mac(mac) = expr.node {
self.check_attributes(&expr.attrs);
- self.collect_bang(mac, expr.span, ExpansionKind::OptExpr).make_opt_expr()
+ self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr).make_opt_expr()
} else {
Some(P(noop_fold_expr(expr, self)))
}
}
pat.and_then(|pat| match pat.node {
- PatKind::Mac(mac) => self.collect_bang(mac, pat.span, ExpansionKind::Pat).make_pat(),
+ PatKind::Mac(mac) => self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat(),
_ => unreachable!(),
})
}
if attr.is_some() || !derives.is_empty() {
return self.collect_attr(attr, derives,
- Annotatable::Stmt(P(stmt_)), ExpansionKind::Stmts)
+ Annotatable::Stmt(P(stmt_)), AstFragmentKind::Stmts)
.make_stmts();
}
if let StmtKind::Mac(mac) = stmt.node {
let (mac, style, attrs) = mac.into_inner();
self.check_attributes(&attrs);
- let mut placeholder = self.collect_bang(mac, stmt.span, ExpansionKind::Stmts)
+ let mut placeholder = self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts)
.make_stmts();
// If this is a macro invocation with a semicolon, then apply that
let (attr, traits, mut item) = self.classify_item(item);
if attr.is_some() || !traits.is_empty() {
let item = Annotatable::Item(item);
- return self.collect_attr(attr, traits, item, ExpansionKind::Items).make_items();
+ return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items();
}
match item.node {
self.check_attributes(&item.attrs);
item.and_then(|item| match item.node {
ItemKind::Mac(mac) => {
- self.collect(ExpansionKind::Items, InvocationKind::Bang {
+ self.collect(AstFragmentKind::Items, InvocationKind::Bang {
mac,
ident: Some(item.ident),
span: item.span,
let (attr, traits, item) = self.classify_item(item);
if attr.is_some() || !traits.is_empty() {
let item = Annotatable::TraitItem(P(item));
- return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems)
+ return self.collect_attr(attr, traits, item, AstFragmentKind::TraitItems)
.make_trait_items()
}
ast::TraitItemKind::Macro(mac) => {
let ast::TraitItem { attrs, span, .. } = item;
self.check_attributes(&attrs);
- self.collect_bang(mac, span, ExpansionKind::TraitItems).make_trait_items()
+ self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
}
_ => fold::noop_fold_trait_item(item, self),
}
let (attr, traits, item) = self.classify_item(item);
if attr.is_some() || !traits.is_empty() {
let item = Annotatable::ImplItem(P(item));
- return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems)
+ return self.collect_attr(attr, traits, item, AstFragmentKind::ImplItems)
.make_impl_items();
}
ast::ImplItemKind::Macro(mac) => {
let ast::ImplItem { attrs, span, .. } = item;
self.check_attributes(&attrs);
- self.collect_bang(mac, span, ExpansionKind::ImplItems).make_impl_items()
+ self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
}
_ => fold::noop_fold_impl_item(item, self),
}
};
match ty.node {
- ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, ExpansionKind::Ty).make_ty(),
+ ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty(),
_ => unreachable!(),
}
}
}
let item = Annotatable::ForeignItem(P(foreign_item));
- return self.collect_attr(attr, traits, item, ExpansionKind::ForeignItems)
+ return self.collect_attr(attr, traits, item, AstFragmentKind::ForeignItems)
.make_foreign_items();
}
GateIssue::Language, explain);
}
- return self.collect_bang(mac, foreign_item.span, ExpansionKind::ForeignItems)
+ return self.collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems)
.make_foreign_items();
}
pub struct Marker(pub Mark);
impl Folder for Marker {
- fn fold_ident(&mut self, mut ident: Ident) -> Ident {
- ident.span = ident.span.apply_mark(self.0);
- ident
- }
-
fn new_span(&mut self, span: Span) -> Span {
span.apply_mark(self.0)
}
use ast::{self, NodeId};
use codemap::{DUMMY_SP, dummy_spanned};
use ext::base::ExtCtxt;
-use ext::expand::{Expansion, ExpansionKind};
+use ext::expand::{AstFragment, AstFragmentKind};
use ext::hygiene::Mark;
use tokenstream::TokenStream;
use fold::*;
use std::collections::HashMap;
-pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
+pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
fn mac_placeholder() -> ast::Mac {
dummy_spanned(ast::Mac_ {
path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
});
match kind {
- ExpansionKind::Expr => Expansion::Expr(expr_placeholder()),
- ExpansionKind::OptExpr => Expansion::OptExpr(Some(expr_placeholder())),
- ExpansionKind::Items => Expansion::Items(SmallVector::one(P(ast::Item {
+ AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
+ AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
+ AstFragmentKind::Items => AstFragment::Items(SmallVector::one(P(ast::Item {
id, span, ident, vis, attrs,
node: ast::ItemKind::Mac(mac_placeholder()),
tokens: None,
}))),
- ExpansionKind::TraitItems => Expansion::TraitItems(SmallVector::one(ast::TraitItem {
+ AstFragmentKind::TraitItems => AstFragment::TraitItems(SmallVector::one(ast::TraitItem {
id, span, ident, attrs, generics,
node: ast::TraitItemKind::Macro(mac_placeholder()),
tokens: None,
})),
- ExpansionKind::ImplItems => Expansion::ImplItems(SmallVector::one(ast::ImplItem {
+ AstFragmentKind::ImplItems => AstFragment::ImplItems(SmallVector::one(ast::ImplItem {
id, span, ident, vis, attrs, generics,
node: ast::ImplItemKind::Macro(mac_placeholder()),
defaultness: ast::Defaultness::Final,
tokens: None,
})),
- ExpansionKind::ForeignItems => Expansion::ForeignItems(SmallVector::one(ast::ForeignItem {
- id, span, ident, vis, attrs,
- node: ast::ForeignItemKind::Macro(mac_placeholder()),
- })),
- ExpansionKind::Pat => Expansion::Pat(P(ast::Pat {
+ AstFragmentKind::ForeignItems =>
+ AstFragment::ForeignItems(SmallVector::one(ast::ForeignItem {
+ id, span, ident, vis, attrs,
+ node: ast::ForeignItemKind::Macro(mac_placeholder()),
+ })),
+ AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
id, span, node: ast::PatKind::Mac(mac_placeholder()),
})),
- ExpansionKind::Ty => Expansion::Ty(P(ast::Ty {
+ AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
id, span, node: ast::TyKind::Mac(mac_placeholder()),
})),
- ExpansionKind::Stmts => Expansion::Stmts(SmallVector::one({
+ AstFragmentKind::Stmts => AstFragment::Stmts(SmallVector::one({
let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::ThinVec::new()));
ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) }
})),
}
pub struct PlaceholderExpander<'a, 'b: 'a> {
- expansions: HashMap<ast::NodeId, Expansion>,
+ expanded_fragments: HashMap<ast::NodeId, AstFragment>,
cx: &'a mut ExtCtxt<'b>,
monotonic: bool,
}
pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
PlaceholderExpander {
cx,
- expansions: HashMap::new(),
+ expanded_fragments: HashMap::new(),
monotonic,
}
}
- pub fn add(&mut self, id: ast::NodeId, expansion: Expansion, derives: Vec<Mark>) {
- let mut expansion = expansion.fold_with(self);
- if let Expansion::Items(mut items) = expansion {
+ pub fn add(&mut self, id: ast::NodeId, fragment: AstFragment, derives: Vec<Mark>) {
+ let mut fragment = fragment.fold_with(self);
+ if let AstFragment::Items(mut items) = fragment {
for derive in derives {
match self.remove(NodeId::placeholder_from_mark(derive)) {
- Expansion::Items(derived_items) => items.extend(derived_items),
+ AstFragment::Items(derived_items) => items.extend(derived_items),
_ => unreachable!(),
}
}
- expansion = Expansion::Items(items);
+ fragment = AstFragment::Items(items);
}
- self.expansions.insert(id, expansion);
+ self.expanded_fragments.insert(id, fragment);
}
- fn remove(&mut self, id: ast::NodeId) -> Expansion {
- self.expansions.remove(&id).unwrap()
+ fn remove(&mut self, id: ast::NodeId) -> AstFragment {
+ self.expanded_fragments.remove(&id).unwrap()
}
}
}
fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
- let (style, mut expansion) = match stmt.node {
+ let (style, mut stmts) = match stmt.node {
ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
_ => return noop_fold_stmt(stmt, self),
};
if style == ast::MacStmtStyle::Semicolon {
- if let Some(stmt) = expansion.pop() {
- expansion.push(stmt.add_trailing_semicolon());
+ if let Some(stmt) = stmts.pop() {
+ stmts.push(stmt.add_trailing_semicolon());
}
}
- expansion
+ stmts
}
fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
use edition::Edition;
use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
use ext::base::{NormalTT, TTMacroExpander};
-use ext::expand::{Expansion, ExpansionKind};
+use ext::expand::{AstFragment, AstFragmentKind};
use ext::tt::macro_parser::{Success, Error, Failure};
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
use ext::tt::macro_parser::{parse, parse_failure_msg};
}
impl<'a> ParserAnyMacro<'a> {
- pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: ExpansionKind) -> Expansion {
+ pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment {
let ParserAnyMacro { site_span, macro_ident, ref mut parser } = *self;
- let expansion = panictry!(parser.parse_expansion(kind, true));
+ let fragment = panictry!(parser.parse_ast_fragment(kind, true));
// We allow semicolons at the end of expressions -- e.g. the semicolon in
// `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`,
// but `m!()` is allowed in expression positions (c.f. issue #34706).
- if kind == ExpansionKind::Expr && parser.token == token::Semi {
+ if kind == AstFragmentKind::Expr && parser.token == token::Semi {
parser.bump();
}
// Make sure we don't have any tokens left to parse so we don't silently drop anything.
let path = ast::Path::from_ident(macro_ident.with_span_pos(site_span));
parser.ensure_complete_parse(&path, kind.name(), site_span);
- expansion
+ fragment
}
}
html_root_url = "https://doc.rust-lang.org/nightly/",
test(attr(deny(warnings))))]
-#![feature(unicode_internals)]
-#![feature(rustc_diagnostic_macros)]
-#![feature(slice_sort_by_cached_key)]
#![feature(const_atomic_usize_new)]
+#![feature(crate_visibility_modifier)]
+#![feature(macro_at_most_once_rep)]
#![feature(rustc_attrs)]
+#![feature(rustc_diagnostic_macros)]
+#![feature(slice_sort_by_cached_key)]
#![feature(str_escape)]
-#![feature(crate_visibility_modifier)]
+#![feature(unicode_internals)]
#![recursion_limit="256"]
use attr;
use codemap::{self, CodeMap};
use syntax_pos::{self, BytePos};
-use syntax_pos::hygiene::{Mark, MarkKind, SyntaxContext};
+use syntax_pos::hygiene::{Mark, SyntaxContext};
use parse::token::{self, BinOpToken, Token};
use parse::lexer::comments;
use parse::{self, ParseSess};
fn print_dollar_crate(&mut self, mut ctxt: SyntaxContext) -> io::Result<()> {
if let Some(mark) = ctxt.adjust(Mark::root()) {
// Make a best effort to print something that complies
- if mark.kind() == MarkKind::Builtin {
+ if mark.is_builtin() {
if let Some(name) = std_inject::injected_crate_name() {
self.writer().word("::")?;
self.writer().word(name)?;
use ext::hygiene::{Mark, SyntaxContext};
use symbol::{Symbol, keywords};
use syntax_pos::{DUMMY_SP, Span};
-use codemap::{ExpnInfo, NameAndSpan, MacroAttribute, dummy_spanned, hygiene, respan};
+use codemap::{ExpnInfo, MacroAttribute, dummy_spanned, hygiene, respan};
use ptr::P;
use tokenstream::TokenStream;
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo {
call_site: DUMMY_SP,
- callee: NameAndSpan {
- format: MacroAttribute(Symbol::intern("std_inject")),
- span: None,
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- }
+ def_site: None,
+ format: MacroAttribute(Symbol::intern("std_inject")),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
}
use attr::{self, HasAttrs};
use syntax_pos::{self, DUMMY_SP, NO_EXPANSION, Span, FileMap, BytePos};
-use codemap::{self, CodeMap, ExpnInfo, NameAndSpan, MacroAttribute, dummy_spanned};
+use codemap::{self, CodeMap, ExpnInfo, MacroAttribute, dummy_spanned};
use errors;
use config;
use entry::{self, EntryPointType};
mark.set_expn_info(ExpnInfo {
call_site: DUMMY_SP,
- callee: NameAndSpan {
- format: MacroAttribute(Symbol::intern("test")),
- span: None,
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- }
+ def_site: None,
+ format: MacroAttribute(Symbol::intern("test")),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
TestHarnessGenerator {
intrinsic: &str,
args: Vec<P<ast::Expr>>)
-> P<ast::Expr> {
- if cx.current_expansion.mark.expn_info().unwrap().callee.allow_internal_unstable {
+ if cx.current_expansion.mark.expn_info().unwrap().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.callee.allow_internal_unstable = true;
+ info.allow_internal_unstable = true;
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(info);
span = span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
use syntax::ast::{self, Ident, NodeId};
use syntax::attr;
-use syntax::codemap::{ExpnInfo, NameAndSpan, MacroAttribute, hygiene, respan};
+use syntax::codemap::{ExpnInfo, MacroAttribute, hygiene, respan};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::expand::ExpansionConfig;
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo {
call_site: DUMMY_SP,
- callee: NameAndSpan {
- format: MacroAttribute(Symbol::intern("proc_macro")),
- span: None,
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- }
+ def_site: None,
+ format: MacroAttribute(Symbol::intern("proc_macro")),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
let span = DUMMY_SP.apply_mark(mark);
#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
pub struct SyntaxContext(pub(super) u32);
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub struct SyntaxContextData {
pub outer_mark: Mark,
pub prev_ctxt: SyntaxContext,
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct Mark(u32);
+#[derive(Debug)]
struct MarkData {
parent: Mark,
- kind: MarkKind,
+ transparency: Transparency,
+ is_builtin: bool,
expn_info: Option<ExpnInfo>,
}
-#[derive(Copy, Clone, PartialEq, Eq)]
-pub enum MarkKind {
- Modern,
- Builtin,
- Legacy,
+/// A property of a macro expansion that determines how identifiers
+/// produced by that expansion are resolved.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+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.
+ /// (Not used yet.)
+ Transparent,
+ /// Identifier produced by a semi-transparent expansion may be resolved
+ /// either at call-site or at definition-site.
+ /// If it's a local variable, label or `$crate` then it's resolved at def-site.
+ /// Otherwise it's resolved at call-site.
+ /// `macro_rules` macros behave like this, built-in macros currently behave like this too,
+ /// but that's an implementation detail.
+ SemiTransparent,
+ /// Identifier produced by an opaque expansion is always resolved at definition-site.
+ /// Def-site spans in procedural macros, identifiers from `macro` by default use this.
+ Opaque,
}
impl Mark {
pub fn fresh(parent: Mark) -> Self {
HygieneData::with(|data| {
- data.marks.push(MarkData { parent: parent, kind: MarkKind::Legacy, expn_info: None });
+ data.marks.push(MarkData {
+ parent,
+ // By default expansions behave like `macro_rules`.
+ transparency: Transparency::SemiTransparent,
+ is_builtin: false,
+ expn_info: None,
+ });
Mark(data.marks.len() as u32 - 1)
})
}
#[inline]
pub fn set_expn_info(self, info: ExpnInfo) {
- HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info))
+ HygieneData::with(|data| {
+ let old_info = &mut data.marks[self.0 as usize].expn_info;
+ if let Some(old_info) = old_info {
+ panic!("expansion info is reset for the mark {}\nold: {:#?}\nnew: {:#?}",
+ self.0, old_info, info);
+ }
+ *old_info = Some(info);
+ })
}
pub fn modern(mut self) -> Mark {
HygieneData::with(|data| {
- loop {
- if self == Mark::root() || data.marks[self.0 as usize].kind == MarkKind::Modern {
- return self;
- }
+ while data.marks[self.0 as usize].transparency != Transparency::Opaque {
self = data.marks[self.0 as usize].parent;
}
+ self
})
}
#[inline]
- pub fn kind(self) -> MarkKind {
- HygieneData::with(|data| data.marks[self.0 as usize].kind)
+ pub fn transparency(self) -> Transparency {
+ assert_ne!(self, Mark::root());
+ HygieneData::with(|data| data.marks[self.0 as usize].transparency)
}
#[inline]
- pub fn set_kind(self, kind: MarkKind) {
- HygieneData::with(|data| data.marks[self.0 as usize].kind = kind)
+ pub fn set_transparency(self, transparency: Transparency) {
+ assert_ne!(self, Mark::root());
+ HygieneData::with(|data| data.marks[self.0 as usize].transparency = transparency)
+ }
+
+ #[inline]
+ pub fn is_builtin(self) -> bool {
+ HygieneData::with(|data| data.marks[self.0 as usize].is_builtin)
+ }
+
+ #[inline]
+ pub fn set_is_builtin(self, is_builtin: bool) {
+ HygieneData::with(|data| data.marks[self.0 as usize].is_builtin = is_builtin)
}
pub fn is_descendant_of(mut self, ancestor: Mark) -> bool {
}
}
+#[derive(Debug)]
pub struct HygieneData {
marks: Vec<MarkData>,
syntax_contexts: Vec<SyntaxContextData>,
HygieneData {
marks: vec![MarkData {
parent: Mark::root(),
- kind: MarkKind::Builtin,
+ // If the root is opaque, then loops searching for an opaque mark
+ // will automatically stop after reaching it.
+ transparency: Transparency::Opaque,
+ is_builtin: true,
expn_info: None,
}],
syntax_contexts: vec![SyntaxContextData {
HygieneData::with(|data| {
data.marks.push(MarkData {
parent: Mark::root(),
- kind: MarkKind::Legacy,
- expn_info: Some(expansion_info)
+ transparency: Transparency::SemiTransparent,
+ is_builtin: false,
+ expn_info: Some(expansion_info),
});
let mark = Mark(data.marks.len() as u32 - 1);
/// Extend a syntax context with a given mark
pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
- if mark.kind() == MarkKind::Modern {
+ if mark.transparency() == Transparency::Opaque {
return self.apply_mark_internal(mark);
}
HygieneData::with(|data| {
let syntax_contexts = &mut data.syntax_contexts;
let mut modern = syntax_contexts[self.0 as usize].modern;
- if data.marks[mark.0 as usize].kind == MarkKind::Modern {
+ if data.marks[mark.0 as usize].transparency == Transparency::Opaque {
modern = *data.markings.entry((modern, mark)).or_insert_with(|| {
let len = syntax_contexts.len() as u32;
syntax_contexts.push(SyntaxContextData {
/// call_site span would have its own ExpnInfo, with the call_site
/// pointing to the `foo!` invocation.
pub call_site: Span,
- /// Information about the expansion.
- pub callee: NameAndSpan
-}
-
-#[derive(Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
-pub struct NameAndSpan {
+ /// 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<Span>,
/// The format with which the macro was invoked.
pub format: ExpnFormat,
/// Whether the macro is allowed to use #[unstable]/feature-gated
pub allow_internal_unsafe: bool,
/// Edition of the crate in which the macro is defined.
pub edition: Edition,
- /// 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.
- pub span: Option<Span>
-}
-
-impl NameAndSpan {
- pub fn name(&self) -> Symbol {
- match self.format {
- ExpnFormat::MacroAttribute(s) |
- ExpnFormat::MacroBang(s) => s,
- ExpnFormat::CompilerDesugaring(ref kind) => kind.as_symbol(),
- }
- }
}
/// The source of expansion.
CompilerDesugaring(CompilerDesugaringKind)
}
+impl ExpnFormat {
+ pub fn name(&self) -> Symbol {
+ match *self {
+ ExpnFormat::MacroBang(name) | ExpnFormat::MacroAttribute(name) => name,
+ ExpnFormat::CompilerDesugaring(kind) => kind.name(),
+ }
+ }
+}
+
/// The kind of compiler desugaring.
-#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum CompilerDesugaringKind {
DotFill,
QuestionMark,
}
impl CompilerDesugaringKind {
- pub fn as_symbol(&self) -> Symbol {
- use CompilerDesugaringKind::*;
- let s = match *self {
- Async => "async",
- DotFill => "...",
- QuestionMark => "?",
- Catch => "do catch",
- ExistentialReturnType => "existental type",
- };
- Symbol::intern(s)
+ pub fn name(self) -> Symbol {
+ Symbol::intern(match self {
+ CompilerDesugaringKind::Async => "async",
+ CompilerDesugaringKind::DotFill => "...",
+ CompilerDesugaringKind::QuestionMark => "?",
+ CompilerDesugaringKind::Catch => "do catch",
+ CompilerDesugaringKind::ExistentialReturnType => "existental type",
+ })
}
}
pub mod edition;
pub mod hygiene;
-pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind};
+pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, CompilerDesugaringKind};
mod span_encoding;
pub use span_encoding::{Span, DUMMY_SP};
/// Edition of the crate from which this span came.
pub fn edition(self) -> edition::Edition {
self.ctxt().outer().expn_info().map_or_else(|| hygiene::default_edition(),
- |einfo| einfo.callee.edition)
+ |einfo| einfo.edition)
}
/// Return the source callee.
///
- /// Returns None if the supplied span has no expansion trace,
- /// else returns the NameAndSpan for the macro definition
+ /// Returns `None` if the supplied span has no expansion trace,
+ /// else returns the `ExpnInfo` for the macro definition
/// corresponding to the source callsite.
- pub fn source_callee(self) -> Option<NameAndSpan> {
- fn source_callee(info: ExpnInfo) -> NameAndSpan {
+ pub fn source_callee(self) -> Option<ExpnInfo> {
+ fn source_callee(info: ExpnInfo) -> ExpnInfo {
match info.call_site.ctxt().outer().expn_info() {
Some(info) => source_callee(info),
- None => info.callee,
+ None => info,
}
}
self.ctxt().outer().expn_info().map(source_callee)
/// `#[allow_internal_unstable]`).
pub fn allows_unstable(&self) -> bool {
match self.ctxt().outer().expn_info() {
- Some(info) => info.callee.allow_internal_unstable,
+ Some(info) => info.allow_internal_unstable,
None => false,
}
}
/// Check if this span arises from a compiler desugaring of kind `kind`.
pub fn is_compiler_desugaring(&self, kind: CompilerDesugaringKind) -> bool {
match self.ctxt().outer().expn_info() {
- Some(info) => match info.callee.format {
+ Some(info) => match info.format {
ExpnFormat::CompilerDesugaring(k) => k == kind,
_ => false,
},
/// if this span is not from a desugaring.
pub fn compiler_desugaring_kind(&self) -> Option<CompilerDesugaringKind> {
match self.ctxt().outer().expn_info() {
- Some(info) => match info.callee.format {
+ Some(info) => match info.format {
ExpnFormat::CompilerDesugaring(k) => Some(k),
_ => None
},
// (that is, a macro marked with `#[allow_internal_unsafe]`).
pub fn allows_unsafe(&self) -> bool {
match self.ctxt().outer().expn_info() {
- Some(info) => info.callee.allow_internal_unsafe,
+ Some(info) => info.allow_internal_unsafe,
None => false,
}
}
let mut prev_span = DUMMY_SP;
let mut result = vec![];
while let Some(info) = self.ctxt().outer().expn_info() {
- let (pre, post) = match info.callee.format {
- ExpnFormat::MacroAttribute(..) => ("#[", "]"),
- ExpnFormat::MacroBang(..) => ("", "!"),
- ExpnFormat::CompilerDesugaring(..) => ("desugaring of `", "`"),
- };
- let macro_decl_name = format!("{}{}{}", pre, info.callee.name(), post);
- let def_site_span = info.callee.span;
-
// Don't print recursive invocations
if !info.call_site.source_equal(&prev_span) {
+ let (pre, post) = match info.format {
+ ExpnFormat::MacroAttribute(..) => ("#[", "]"),
+ ExpnFormat::MacroBang(..) => ("", "!"),
+ ExpnFormat::CompilerDesugaring(..) => ("desugaring of `", "`"),
+ };
result.push(MacroBacktrace {
call_site: info.call_site,
- macro_decl_name,
- def_site_span,
+ macro_decl_name: format!("{}{}{}", pre, info.format.name(), post),
+ def_site_span: info.def_site,
});
}
-Subproject commit 08da30d72c9abfff4d41f6f081e31fd2929b820d
+Subproject commit 87edd75ecf26c9084969f431bb5e363693a8a4ca