mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
Auto merge of #86676 - cjgillot:localexpn, r=petrochenkov
Make expansions stable for incr. comp. This PR aims to make expansions stable for incr. comp. by using the same architecture as definitions: - the interned identifier `ExpnId` contains a `CrateNum` and a crate-local id; - bidirectional maps `ExpnHash <-> ExpnId` are setup; - incr. comp. on-disk cache saves and reconstructs expansions using their `ExpnHash`. I tried to use as many `LocalExpnId` as I could in the resolver code, but I may have missed a few opportunities. All this will allow to use an `ExpnId` as a query key, and to force this query without recomputing caller queries. For instance, this will be used to implement #85999. r? `@petrochenkov`
This commit is contained in:
commit
68511b574f
@ -1,4 +1,4 @@
|
|||||||
use rustc_span::ExpnId;
|
use rustc_span::LocalExpnId;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
rustc_index::newtype_index! {
|
rustc_index::newtype_index! {
|
||||||
@ -24,12 +24,12 @@ pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
|
|||||||
pub const DUMMY_NODE_ID: NodeId = NodeId::MAX;
|
pub const DUMMY_NODE_ID: NodeId = NodeId::MAX;
|
||||||
|
|
||||||
impl NodeId {
|
impl NodeId {
|
||||||
pub fn placeholder_from_expn_id(expn_id: ExpnId) -> Self {
|
pub fn placeholder_from_expn_id(expn_id: LocalExpnId) -> Self {
|
||||||
NodeId::from_u32(expn_id.as_u32())
|
NodeId::from_u32(expn_id.as_u32())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn placeholder_to_expn_id(self) -> ExpnId {
|
pub fn placeholder_to_expn_id(self) -> LocalExpnId {
|
||||||
ExpnId::from_u32(self.as_u32())
|
LocalExpnId::from_u32(self.as_u32())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,8 +36,9 @@ pub fn expand_deriving_clone(
|
|||||||
Annotatable::Item(ref annitem) => match annitem.kind {
|
Annotatable::Item(ref annitem) => match annitem.kind {
|
||||||
ItemKind::Struct(_, Generics { ref params, .. })
|
ItemKind::Struct(_, Generics { ref params, .. })
|
||||||
| ItemKind::Enum(_, Generics { ref params, .. }) => {
|
| ItemKind::Enum(_, Generics { ref params, .. }) => {
|
||||||
let container_id = cx.current_expansion.id.expn_data().parent;
|
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
|
||||||
if cx.resolver.has_derive_copy(container_id)
|
let has_derive_copy = cx.resolver.has_derive_copy(container_id);
|
||||||
|
if has_derive_copy
|
||||||
&& !params
|
&& !params
|
||||||
.iter()
|
.iter()
|
||||||
.any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
|
.any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
|
||||||
|
@ -410,7 +410,7 @@ impl<'a> TraitDef<'a> {
|
|||||||
.any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })),
|
.any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let container_id = cx.current_expansion.id.expn_data().parent;
|
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
|
||||||
let always_copy = has_no_type_params && cx.resolver.has_derive_copy(container_id);
|
let always_copy = has_no_type_params && cx.resolver.has_derive_copy(container_id);
|
||||||
let use_temporaries = is_packed && always_copy;
|
let use_temporaries = is_packed && always_copy;
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ fn mk_decls(
|
|||||||
&[sym::rustc_attrs, sym::proc_macro_internals],
|
&[sym::rustc_attrs, sym::proc_macro_internals],
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let span = DUMMY_SP.with_def_site_ctxt(expn_id);
|
let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
|
||||||
|
|
||||||
let proc_macro = Ident::new(sym::proc_macro, span);
|
let proc_macro = Ident::new(sym::proc_macro, span);
|
||||||
let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None));
|
let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None));
|
||||||
|
@ -34,8 +34,8 @@ pub fn inject(
|
|||||||
&[sym::prelude_import],
|
&[sym::prelude_import],
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let span = DUMMY_SP.with_def_site_ctxt(expn_id);
|
let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
|
||||||
let call_site = DUMMY_SP.with_call_site_ctxt(expn_id);
|
let call_site = DUMMY_SP.with_call_site_ctxt(expn_id.to_expn_id());
|
||||||
|
|
||||||
let ecfg = ExpansionConfig::default("std_lib_injection".to_string());
|
let ecfg = ExpansionConfig::default("std_lib_injection".to_string());
|
||||||
let cx = ExtCtxt::new(sess, ecfg, resolver, None);
|
let cx = ExtCtxt::new(sess, ecfg, resolver, None);
|
||||||
|
@ -126,7 +126,8 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
|
|||||||
for test in &mut tests {
|
for test in &mut tests {
|
||||||
// See the comment on `mk_main` for why we're using
|
// See the comment on `mk_main` for why we're using
|
||||||
// `apply_mark` directly.
|
// `apply_mark` directly.
|
||||||
test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque);
|
test.ident.span =
|
||||||
|
test.ident.span.apply_mark(expn_id.to_expn_id(), Transparency::Opaque);
|
||||||
}
|
}
|
||||||
self.cx.test_cases.extend(tests);
|
self.cx.test_cases.extend(tests);
|
||||||
}
|
}
|
||||||
@ -223,7 +224,7 @@ fn generate_test_harness(
|
|||||||
&[sym::test, sym::rustc_attrs],
|
&[sym::test, sym::rustc_attrs],
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let def_site = DUMMY_SP.with_def_site_ctxt(expn_id);
|
let def_site = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
|
||||||
|
|
||||||
// Remove the entry points
|
// Remove the entry points
|
||||||
let mut cleaner = EntryPointCleaner { sess, depth: 0, def_site };
|
let mut cleaner = EntryPointCleaner { sess, depth: 0, def_site };
|
||||||
|
@ -16,7 +16,7 @@ use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
|
|||||||
use rustc_session::{parse::ParseSess, Limit, Session};
|
use rustc_session::{parse::ParseSess, Limit, Session};
|
||||||
use rustc_span::def_id::{CrateNum, DefId};
|
use rustc_span::def_id::{CrateNum, DefId};
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
|
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
|
||||||
use rustc_span::source_map::SourceMap;
|
use rustc_span::source_map::SourceMap;
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP};
|
use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP};
|
||||||
@ -813,7 +813,7 @@ impl SyntaxExtension {
|
|||||||
|
|
||||||
pub fn expn_data(
|
pub fn expn_data(
|
||||||
&self,
|
&self,
|
||||||
parent: ExpnId,
|
parent: LocalExpnId,
|
||||||
call_site: Span,
|
call_site: Span,
|
||||||
descr: Symbol,
|
descr: Symbol,
|
||||||
macro_def_id: Option<DefId>,
|
macro_def_id: Option<DefId>,
|
||||||
@ -821,7 +821,7 @@ impl SyntaxExtension {
|
|||||||
) -> ExpnData {
|
) -> ExpnData {
|
||||||
ExpnData::new(
|
ExpnData::new(
|
||||||
ExpnKind::Macro(self.macro_kind(), descr),
|
ExpnKind::Macro(self.macro_kind(), descr),
|
||||||
parent,
|
parent.to_expn_id(),
|
||||||
call_site,
|
call_site,
|
||||||
self.span,
|
self.span,
|
||||||
self.allow_internal_unstable.clone(),
|
self.allow_internal_unstable.clone(),
|
||||||
@ -843,7 +843,11 @@ pub trait ResolverExpand {
|
|||||||
fn next_node_id(&mut self) -> NodeId;
|
fn next_node_id(&mut self) -> NodeId;
|
||||||
|
|
||||||
fn resolve_dollar_crates(&mut self);
|
fn resolve_dollar_crates(&mut self);
|
||||||
fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment);
|
fn visit_ast_fragment_with_placeholders(
|
||||||
|
&mut self,
|
||||||
|
expn_id: LocalExpnId,
|
||||||
|
fragment: &AstFragment,
|
||||||
|
);
|
||||||
fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind);
|
fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind);
|
||||||
|
|
||||||
fn expansion_for_ast_pass(
|
fn expansion_for_ast_pass(
|
||||||
@ -852,37 +856,41 @@ pub trait ResolverExpand {
|
|||||||
pass: AstPass,
|
pass: AstPass,
|
||||||
features: &[Symbol],
|
features: &[Symbol],
|
||||||
parent_module_id: Option<NodeId>,
|
parent_module_id: Option<NodeId>,
|
||||||
) -> ExpnId;
|
) -> LocalExpnId;
|
||||||
|
|
||||||
fn resolve_imports(&mut self);
|
fn resolve_imports(&mut self);
|
||||||
|
|
||||||
fn resolve_macro_invocation(
|
fn resolve_macro_invocation(
|
||||||
&mut self,
|
&mut self,
|
||||||
invoc: &Invocation,
|
invoc: &Invocation,
|
||||||
eager_expansion_root: ExpnId,
|
eager_expansion_root: LocalExpnId,
|
||||||
force: bool,
|
force: bool,
|
||||||
) -> Result<Lrc<SyntaxExtension>, Indeterminate>;
|
) -> Result<Lrc<SyntaxExtension>, Indeterminate>;
|
||||||
|
|
||||||
fn check_unused_macros(&mut self);
|
fn check_unused_macros(&mut self);
|
||||||
|
|
||||||
/// Some parent node that is close enough to the given macro call.
|
/// Some parent node that is close enough to the given macro call.
|
||||||
fn lint_node_id(&self, expn_id: ExpnId) -> NodeId;
|
fn lint_node_id(&self, expn_id: LocalExpnId) -> NodeId;
|
||||||
|
|
||||||
// Resolver interfaces for specific built-in macros.
|
// Resolver interfaces for specific built-in macros.
|
||||||
/// Does `#[derive(...)]` attribute with the given `ExpnId` have built-in `Copy` inside it?
|
/// Does `#[derive(...)]` attribute with the given `ExpnId` have built-in `Copy` inside it?
|
||||||
fn has_derive_copy(&self, expn_id: ExpnId) -> bool;
|
fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool;
|
||||||
/// Resolve paths inside the `#[derive(...)]` attribute with the given `ExpnId`.
|
/// Resolve paths inside the `#[derive(...)]` attribute with the given `ExpnId`.
|
||||||
fn resolve_derives(
|
fn resolve_derives(
|
||||||
&mut self,
|
&mut self,
|
||||||
expn_id: ExpnId,
|
expn_id: LocalExpnId,
|
||||||
force: bool,
|
force: bool,
|
||||||
derive_paths: &dyn Fn() -> DeriveResolutions,
|
derive_paths: &dyn Fn() -> DeriveResolutions,
|
||||||
) -> Result<(), Indeterminate>;
|
) -> Result<(), Indeterminate>;
|
||||||
/// Take resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId`
|
/// Take resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId`
|
||||||
/// back from resolver.
|
/// back from resolver.
|
||||||
fn take_derive_resolutions(&mut self, expn_id: ExpnId) -> Option<DeriveResolutions>;
|
fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option<DeriveResolutions>;
|
||||||
/// Path resolution logic for `#[cfg_accessible(path)]`.
|
/// Path resolution logic for `#[cfg_accessible(path)]`.
|
||||||
fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
|
fn cfg_accessible(
|
||||||
|
&mut self,
|
||||||
|
expn_id: LocalExpnId,
|
||||||
|
path: &ast::Path,
|
||||||
|
) -> Result<bool, Indeterminate>;
|
||||||
|
|
||||||
/// Decodes the proc-macro quoted span in the specified crate, with the specified id.
|
/// Decodes the proc-macro quoted span in the specified crate, with the specified id.
|
||||||
/// No caching is performed.
|
/// No caching is performed.
|
||||||
@ -913,7 +921,7 @@ impl ModuleData {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ExpansionData {
|
pub struct ExpansionData {
|
||||||
pub id: ExpnId,
|
pub id: LocalExpnId,
|
||||||
pub depth: usize,
|
pub depth: usize,
|
||||||
pub module: Rc<ModuleData>,
|
pub module: Rc<ModuleData>,
|
||||||
pub dir_ownership: DirOwnership,
|
pub dir_ownership: DirOwnership,
|
||||||
@ -958,7 +966,7 @@ impl<'a> ExtCtxt<'a> {
|
|||||||
extern_mod_loaded,
|
extern_mod_loaded,
|
||||||
root_path: PathBuf::new(),
|
root_path: PathBuf::new(),
|
||||||
current_expansion: ExpansionData {
|
current_expansion: ExpansionData {
|
||||||
id: ExpnId::root(),
|
id: LocalExpnId::ROOT,
|
||||||
depth: 0,
|
depth: 0,
|
||||||
module: Default::default(),
|
module: Default::default(),
|
||||||
dir_ownership: DirOwnership::Owned { relative: None },
|
dir_ownership: DirOwnership::Owned { relative: None },
|
||||||
@ -995,19 +1003,19 @@ impl<'a> ExtCtxt<'a> {
|
|||||||
/// Equivalent of `Span::def_site` from the proc macro API,
|
/// Equivalent of `Span::def_site` from the proc macro API,
|
||||||
/// except that the location is taken from the span passed as an argument.
|
/// except that the location is taken from the span passed as an argument.
|
||||||
pub fn with_def_site_ctxt(&self, span: Span) -> Span {
|
pub fn with_def_site_ctxt(&self, span: Span) -> Span {
|
||||||
span.with_def_site_ctxt(self.current_expansion.id)
|
span.with_def_site_ctxt(self.current_expansion.id.to_expn_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equivalent of `Span::call_site` from the proc macro API,
|
/// Equivalent of `Span::call_site` from the proc macro API,
|
||||||
/// except that the location is taken from the span passed as an argument.
|
/// except that the location is taken from the span passed as an argument.
|
||||||
pub fn with_call_site_ctxt(&self, span: Span) -> Span {
|
pub fn with_call_site_ctxt(&self, span: Span) -> Span {
|
||||||
span.with_call_site_ctxt(self.current_expansion.id)
|
span.with_call_site_ctxt(self.current_expansion.id.to_expn_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equivalent of `Span::mixed_site` from the proc macro API,
|
/// Equivalent of `Span::mixed_site` from the proc macro API,
|
||||||
/// except that the location is taken from the span passed as an argument.
|
/// except that the location is taken from the span passed as an argument.
|
||||||
pub fn with_mixed_site_ctxt(&self, span: Span) -> Span {
|
pub fn with_mixed_site_ctxt(&self, span: Span) -> Span {
|
||||||
span.with_mixed_site_ctxt(self.current_expansion.id)
|
span.with_mixed_site_ctxt(self.current_expansion.id.to_expn_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns span for the macro which originally caused the current expansion to happen.
|
/// Returns span for the macro which originally caused the current expansion to happen.
|
||||||
|
@ -31,7 +31,7 @@ use rustc_session::lint::BuiltinLintDiagnostics;
|
|||||||
use rustc_session::parse::{feature_err, ParseSess};
|
use rustc_session::parse::{feature_err, ParseSess};
|
||||||
use rustc_session::Limit;
|
use rustc_session::Limit;
|
||||||
use rustc_span::symbol::{sym, Ident};
|
use rustc_span::symbol::{sym, Ident};
|
||||||
use rustc_span::{ExpnId, FileName, Span};
|
use rustc_span::{FileName, LocalExpnId, Span};
|
||||||
|
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
@ -508,7 +508,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
.map(|(path, item, _exts)| {
|
.map(|(path, item, _exts)| {
|
||||||
// FIXME: Consider using the derive resolutions (`_exts`)
|
// FIXME: Consider using the derive resolutions (`_exts`)
|
||||||
// instead of enqueuing the derives to be resolved again later.
|
// instead of enqueuing the derives to be resolved again later.
|
||||||
let expn_id = ExpnId::fresh_empty();
|
let expn_id = LocalExpnId::fresh_empty();
|
||||||
derive_invocations.push((
|
derive_invocations.push((
|
||||||
Invocation {
|
Invocation {
|
||||||
kind: InvocationKind::Derive { path, item },
|
kind: InvocationKind::Derive { path, item },
|
||||||
@ -993,7 +993,7 @@ struct InvocationCollector<'a, 'b> {
|
|||||||
|
|
||||||
impl<'a, 'b> InvocationCollector<'a, 'b> {
|
impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
|
fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
|
||||||
let expn_id = ExpnId::fresh_empty();
|
let expn_id = LocalExpnId::fresh_empty();
|
||||||
let vis = kind.placeholder_visibility();
|
let vis = kind.placeholder_visibility();
|
||||||
self.invocations.push((
|
self.invocations.push((
|
||||||
Invocation {
|
Invocation {
|
||||||
|
@ -8,7 +8,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
|
|||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_errors::{pluralize, PResult};
|
use rustc_errors::{pluralize, PResult};
|
||||||
use rustc_span::hygiene::{ExpnId, Transparency};
|
use rustc_span::hygiene::{LocalExpnId, Transparency};
|
||||||
use rustc_span::symbol::MacroRulesNormalizedIdent;
|
use rustc_span::symbol::MacroRulesNormalizedIdent;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ use smallvec::{smallvec, SmallVec};
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
// A Marker adds the given mark to the syntax context.
|
// A Marker adds the given mark to the syntax context.
|
||||||
struct Marker(ExpnId, Transparency);
|
struct Marker(LocalExpnId, Transparency);
|
||||||
|
|
||||||
impl MutVisitor for Marker {
|
impl MutVisitor for Marker {
|
||||||
fn token_visiting_enabled(&self) -> bool {
|
fn token_visiting_enabled(&self) -> bool {
|
||||||
@ -24,7 +24,7 @@ impl MutVisitor for Marker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_span(&mut self, span: &mut Span) {
|
fn visit_span(&mut self, span: &mut Span) {
|
||||||
*span = span.apply_mark(self.0, self.1)
|
*span = span.apply_mark(self.0.to_expn_id(), self.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,13 +30,12 @@ use rustc_middle::ty::codec::TyDecoder;
|
|||||||
use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
|
use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
|
||||||
use rustc_serialize::{opaque, Decodable, Decoder};
|
use rustc_serialize::{opaque, Decodable, Decoder};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::hygiene::ExpnDataDecodeMode;
|
use rustc_span::hygiene::{ExpnIndex, MacroKind};
|
||||||
use rustc_span::source_map::{respan, Spanned};
|
use rustc_span::source_map::{respan, Spanned};
|
||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||||
use rustc_span::{self, hygiene::MacroKind, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
|
use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
|
||||||
|
|
||||||
use proc_macro::bridge::client::ProcMacro;
|
use proc_macro::bridge::client::ProcMacro;
|
||||||
use std::cell::Cell;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
@ -80,6 +79,8 @@ crate struct CrateMetadata {
|
|||||||
/// `DefIndex`. See `raw_def_id_to_def_id` for more details about how
|
/// `DefIndex`. See `raw_def_id_to_def_id` for more details about how
|
||||||
/// this is used.
|
/// this is used.
|
||||||
def_path_hash_map: OnceCell<UnhashMap<DefPathHash, DefIndex>>,
|
def_path_hash_map: OnceCell<UnhashMap<DefPathHash, DefIndex>>,
|
||||||
|
/// Likewise for ExpnHash.
|
||||||
|
expn_hash_map: OnceCell<UnhashMap<ExpnHash, ExpnIndex>>,
|
||||||
/// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
|
/// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
|
||||||
alloc_decoding_state: AllocDecodingState,
|
alloc_decoding_state: AllocDecodingState,
|
||||||
/// Caches decoded `DefKey`s.
|
/// Caches decoded `DefKey`s.
|
||||||
@ -350,6 +351,12 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnIndex {
|
||||||
|
fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<ExpnIndex, String> {
|
||||||
|
Ok(ExpnIndex::from_u32(d.read_u32()?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
|
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
|
||||||
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<SyntaxContext, String> {
|
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<SyntaxContext, String> {
|
||||||
let cdata = decoder.cdata();
|
let cdata = decoder.cdata();
|
||||||
@ -371,43 +378,35 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
|
|||||||
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<ExpnId, String> {
|
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<ExpnId, String> {
|
||||||
let local_cdata = decoder.cdata();
|
let local_cdata = decoder.cdata();
|
||||||
let sess = decoder.sess.unwrap();
|
let sess = decoder.sess.unwrap();
|
||||||
let expn_cnum = Cell::new(None);
|
|
||||||
let get_ctxt = |cnum| {
|
|
||||||
expn_cnum.set(Some(cnum));
|
|
||||||
if cnum == LOCAL_CRATE {
|
|
||||||
&local_cdata.hygiene_context
|
|
||||||
} else {
|
|
||||||
&local_cdata.cstore.get_crate_data(cnum).cdata.hygiene_context
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
rustc_span::hygiene::decode_expn_id(
|
let cnum = CrateNum::decode(decoder)?;
|
||||||
decoder,
|
let index = u32::decode(decoder)?;
|
||||||
ExpnDataDecodeMode::Metadata(get_ctxt),
|
|
||||||
|_this, index| {
|
let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |expn_id| {
|
||||||
let cnum = expn_cnum.get().unwrap();
|
let ExpnId { krate: cnum, local_id: index } = expn_id;
|
||||||
// Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s
|
// Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s
|
||||||
// are stored in the owning crate, to avoid duplication.
|
// are stored in the owning crate, to avoid duplication.
|
||||||
let crate_data = if cnum == LOCAL_CRATE {
|
debug_assert_ne!(cnum, LOCAL_CRATE);
|
||||||
local_cdata
|
let crate_data = if cnum == local_cdata.cnum {
|
||||||
} else {
|
local_cdata
|
||||||
local_cdata.cstore.get_crate_data(cnum)
|
} else {
|
||||||
};
|
local_cdata.cstore.get_crate_data(cnum)
|
||||||
let expn_data = crate_data
|
};
|
||||||
.root
|
let expn_data = crate_data
|
||||||
.expn_data
|
.root
|
||||||
.get(&crate_data, index)
|
.expn_data
|
||||||
.unwrap()
|
.get(&crate_data, index)
|
||||||
.decode((&crate_data, sess));
|
.unwrap()
|
||||||
let expn_hash = crate_data
|
.decode((&crate_data, sess));
|
||||||
.root
|
let expn_hash = crate_data
|
||||||
.expn_hashes
|
.root
|
||||||
.get(&crate_data, index)
|
.expn_hashes
|
||||||
.unwrap()
|
.get(&crate_data, index)
|
||||||
.decode((&crate_data, sess));
|
.unwrap()
|
||||||
Ok((expn_data, expn_hash))
|
.decode((&crate_data, sess));
|
||||||
},
|
(expn_data, expn_hash)
|
||||||
)
|
});
|
||||||
|
Ok(expn_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1622,6 +1621,41 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||||||
self.def_path_hash_unlocked(index, &mut def_path_hashes)
|
self.def_path_hash_unlocked(index, &mut def_path_hashes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId {
|
||||||
|
debug_assert_eq!(ExpnId::from_hash(hash), None);
|
||||||
|
let index_guess = ExpnIndex::from_u32(index_guess);
|
||||||
|
let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self));
|
||||||
|
|
||||||
|
let index = if old_hash == Some(hash) {
|
||||||
|
// Fast path: the expn and its index is unchanged from the
|
||||||
|
// previous compilation session. There is no need to decode anything
|
||||||
|
// else.
|
||||||
|
index_guess
|
||||||
|
} else {
|
||||||
|
// Slow path: We need to find out the new `DefIndex` of the provided
|
||||||
|
// `DefPathHash`, if its still exists. This requires decoding every `DefPathHash`
|
||||||
|
// stored in this crate.
|
||||||
|
let map = self.cdata.expn_hash_map.get_or_init(|| {
|
||||||
|
let end_id = self.root.expn_hashes.size() as u32;
|
||||||
|
let mut map =
|
||||||
|
UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
|
||||||
|
for i in 0..end_id {
|
||||||
|
let i = ExpnIndex::from_u32(i);
|
||||||
|
if let Some(hash) = self.root.expn_hashes.get(self, i) {
|
||||||
|
map.insert(hash.decode(self), i);
|
||||||
|
} else {
|
||||||
|
panic!("Missing expn_hash entry for {:?}", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
map
|
||||||
|
});
|
||||||
|
map[&hash]
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = self.root.expn_data.get(self, index).unwrap().decode(self);
|
||||||
|
rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash)
|
||||||
|
}
|
||||||
|
|
||||||
/// Imports the source_map from an external crate into the source_map of the crate
|
/// Imports the source_map from an external crate into the source_map of the crate
|
||||||
/// currently being compiled (the "local crate").
|
/// currently being compiled (the "local crate").
|
||||||
///
|
///
|
||||||
@ -1860,6 +1894,7 @@ impl CrateMetadata {
|
|||||||
raw_proc_macros,
|
raw_proc_macros,
|
||||||
source_map_import_info: OnceCell::new(),
|
source_map_import_info: OnceCell::new(),
|
||||||
def_path_hash_map: Default::default(),
|
def_path_hash_map: Default::default(),
|
||||||
|
expn_hash_map: Default::default(),
|
||||||
alloc_decoding_state,
|
alloc_decoding_state,
|
||||||
cnum,
|
cnum,
|
||||||
cnum_map,
|
cnum_map,
|
||||||
|
@ -18,11 +18,11 @@ use rustc_middle::ty::query::Providers;
|
|||||||
use rustc_middle::ty::{self, TyCtxt, Visibility};
|
use rustc_middle::ty::{self, TyCtxt, Visibility};
|
||||||
use rustc_session::utils::NativeLibKind;
|
use rustc_session::utils::NativeLibKind;
|
||||||
use rustc_session::{Session, StableCrateId};
|
use rustc_session::{Session, StableCrateId};
|
||||||
|
use rustc_span::hygiene::{ExpnHash, ExpnId};
|
||||||
use rustc_span::source_map::{Span, Spanned};
|
use rustc_span::source_map::{Span, Spanned};
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
|
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_span::ExpnId;
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
@ -528,6 +528,10 @@ impl CrateStore for CStore {
|
|||||||
self.get_crate_data(cnum).def_path_hash_to_def_id(cnum, index_guess, hash)
|
self.get_crate_data(cnum).def_path_hash_to_def_id(cnum, index_guess, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId {
|
||||||
|
self.get_crate_data(cnum).expn_hash_to_expn_id(index_guess, hash)
|
||||||
|
}
|
||||||
|
|
||||||
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata {
|
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata {
|
||||||
encoder::encode_metadata(tcx)
|
encoder::encode_metadata(tcx)
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ use rustc_session::config::CrateType;
|
|||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||||
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
|
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
|
||||||
use rustc_span::{
|
use rustc_span::{
|
||||||
hygiene::{ExpnDataEncodeMode, HygieneEncodeContext, MacroKind},
|
hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind},
|
||||||
RealFileName,
|
RealFileName,
|
||||||
};
|
};
|
||||||
use rustc_target::abi::VariantIdx;
|
use rustc_target::abi::VariantIdx;
|
||||||
@ -168,6 +168,12 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnIndex {
|
||||||
|
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
|
||||||
|
s.emit_u32(self.as_u32())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
|
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
|
||||||
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
|
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
|
||||||
rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s)
|
rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s)
|
||||||
@ -176,12 +182,15 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
|
|||||||
|
|
||||||
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
|
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
|
||||||
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
|
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
|
||||||
rustc_span::hygiene::raw_encode_expn_id(
|
if self.krate == LOCAL_CRATE {
|
||||||
*self,
|
// We will only write details for local expansions. Non-local expansions will fetch
|
||||||
&s.hygiene_ctxt,
|
// data from the corresponding crate's metadata.
|
||||||
ExpnDataEncodeMode::Metadata,
|
// FIXME(#43047) FIXME(#74731) We may eventually want to avoid relying on external
|
||||||
s,
|
// metadata from proc-macro crates.
|
||||||
)
|
s.hygiene_ctxt.schedule_expn_data_for_encoding(*self);
|
||||||
|
}
|
||||||
|
self.krate.encode(s)?;
|
||||||
|
self.local_id.encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1593,8 +1602,10 @@ impl EncodeContext<'a, 'tcx> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
|(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
|
|(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
|
||||||
expn_data_table.set(index, this.lazy(expn_data));
|
if let Some(index) = index.as_local() {
|
||||||
expn_hash_table.set(index, this.lazy(hash));
|
expn_data_table.set(index.as_raw(), this.lazy(expn_data));
|
||||||
|
expn_hash_table.set(index.as_raw(), this.lazy(hash));
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -19,7 +19,7 @@ use rustc_middle::ty::{self, ReprOptions, Ty};
|
|||||||
use rustc_serialize::opaque::Encoder;
|
use rustc_serialize::opaque::Encoder;
|
||||||
use rustc_session::config::SymbolManglingVersion;
|
use rustc_session::config::SymbolManglingVersion;
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::hygiene::MacroKind;
|
use rustc_span::hygiene::{ExpnIndex, MacroKind};
|
||||||
use rustc_span::symbol::{Ident, Symbol};
|
use rustc_span::symbol::{Ident, Symbol};
|
||||||
use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span};
|
use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span};
|
||||||
use rustc_target::spec::{PanicStrategy, TargetTriple};
|
use rustc_target::spec::{PanicStrategy, TargetTriple};
|
||||||
@ -170,8 +170,8 @@ macro_rules! Lazy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SyntaxContextTable = Lazy<Table<u32, Lazy<SyntaxContextData>>>;
|
type SyntaxContextTable = Lazy<Table<u32, Lazy<SyntaxContextData>>>;
|
||||||
type ExpnDataTable = Lazy<Table<u32, Lazy<ExpnData>>>;
|
type ExpnDataTable = Lazy<Table<ExpnIndex, Lazy<ExpnData>>>;
|
||||||
type ExpnHashTable = Lazy<Table<u32, Lazy<ExpnHash>>>;
|
type ExpnHashTable = Lazy<Table<ExpnIndex, Lazy<ExpnHash>>>;
|
||||||
|
|
||||||
#[derive(MetadataEncodable, MetadataDecodable)]
|
#[derive(MetadataEncodable, MetadataDecodable)]
|
||||||
crate struct ProcMacroData {
|
crate struct ProcMacroData {
|
||||||
|
@ -6,12 +6,12 @@ use crate::ty::TyCtxt;
|
|||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_data_structures::sync::{self, MetadataRef};
|
use rustc_data_structures::sync::{self, MetadataRef};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{CrateNum, DefId, StableCrateId, LOCAL_CRATE};
|
||||||
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
|
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_session::search_paths::PathKind;
|
use rustc_session::search_paths::PathKind;
|
||||||
use rustc_session::utils::NativeLibKind;
|
use rustc_session::utils::NativeLibKind;
|
||||||
use rustc_session::StableCrateId;
|
use rustc_span::hygiene::{ExpnHash, ExpnId};
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::spec::Target;
|
use rustc_target::spec::Target;
|
||||||
@ -207,6 +207,7 @@ pub trait CrateStore: std::fmt::Debug {
|
|||||||
index_guess: u32,
|
index_guess: u32,
|
||||||
hash: DefPathHash,
|
hash: DefPathHash,
|
||||||
) -> Option<DefId>;
|
) -> Option<DefId>;
|
||||||
|
fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId;
|
||||||
|
|
||||||
// utility functions
|
// utility functions
|
||||||
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata;
|
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata;
|
||||||
|
@ -20,8 +20,7 @@ use rustc_serialize::{
|
|||||||
};
|
};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::hygiene::{
|
use rustc_span::hygiene::{
|
||||||
ExpnDataDecodeMode, ExpnDataEncodeMode, ExpnId, HygieneDecodeContext, HygieneEncodeContext,
|
ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData,
|
||||||
SyntaxContext, SyntaxContextData,
|
|
||||||
};
|
};
|
||||||
use rustc_span::source_map::{SourceMap, StableSourceFileId};
|
use rustc_span::source_map::{SourceMap, StableSourceFileId};
|
||||||
use rustc_span::CachingSourceMapView;
|
use rustc_span::CachingSourceMapView;
|
||||||
@ -84,7 +83,7 @@ pub struct OnDiskCache<'sess> {
|
|||||||
// `ExpnData` (e.g `ExpnData.krate` may not be `LOCAL_CRATE`). Alternatively,
|
// `ExpnData` (e.g `ExpnData.krate` may not be `LOCAL_CRATE`). Alternatively,
|
||||||
// we could look up the `ExpnData` from the metadata of foreign crates,
|
// we could look up the `ExpnData` from the metadata of foreign crates,
|
||||||
// but it seemed easier to have `OnDiskCache` be independent of the `CStore`.
|
// but it seemed easier to have `OnDiskCache` be independent of the `CStore`.
|
||||||
expn_data: FxHashMap<u32, AbsoluteBytePos>,
|
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
|
||||||
// Additional information used when decoding hygiene data.
|
// Additional information used when decoding hygiene data.
|
||||||
hygiene_context: HygieneDecodeContext,
|
hygiene_context: HygieneDecodeContext,
|
||||||
// Maps `DefPathHash`es to their `RawDefId`s from the *previous*
|
// Maps `DefPathHash`es to their `RawDefId`s from the *previous*
|
||||||
@ -92,6 +91,8 @@ pub struct OnDiskCache<'sess> {
|
|||||||
// we try to map a `DefPathHash` to its `DefId` in the current compilation
|
// we try to map a `DefPathHash` to its `DefId` in the current compilation
|
||||||
// session.
|
// session.
|
||||||
foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
|
foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
|
||||||
|
// Likewise for ExpnId.
|
||||||
|
foreign_expn_data: UnhashMap<ExpnHash, u32>,
|
||||||
|
|
||||||
// The *next* compilation sessison's `foreign_def_path_hashes` - at
|
// The *next* compilation sessison's `foreign_def_path_hashes` - at
|
||||||
// the end of our current compilation session, this will get written
|
// the end of our current compilation session, this will get written
|
||||||
@ -119,8 +120,9 @@ struct Footer {
|
|||||||
// See `OnDiskCache.syntax_contexts`
|
// See `OnDiskCache.syntax_contexts`
|
||||||
syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
|
syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
|
||||||
// See `OnDiskCache.expn_data`
|
// See `OnDiskCache.expn_data`
|
||||||
expn_data: FxHashMap<u32, AbsoluteBytePos>,
|
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
|
||||||
foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
|
foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
|
||||||
|
foreign_expn_data: UnhashMap<ExpnHash, u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
|
pub type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
|
||||||
@ -218,6 +220,7 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
|
alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
|
||||||
syntax_contexts: footer.syntax_contexts,
|
syntax_contexts: footer.syntax_contexts,
|
||||||
expn_data: footer.expn_data,
|
expn_data: footer.expn_data,
|
||||||
|
foreign_expn_data: footer.foreign_expn_data,
|
||||||
hygiene_context: Default::default(),
|
hygiene_context: Default::default(),
|
||||||
foreign_def_path_hashes: footer.foreign_def_path_hashes,
|
foreign_def_path_hashes: footer.foreign_def_path_hashes,
|
||||||
latest_foreign_def_path_hashes: Default::default(),
|
latest_foreign_def_path_hashes: Default::default(),
|
||||||
@ -237,7 +240,8 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
prev_diagnostics_index: Default::default(),
|
prev_diagnostics_index: Default::default(),
|
||||||
alloc_decoding_state: AllocDecodingState::new(Vec::new()),
|
alloc_decoding_state: AllocDecodingState::new(Vec::new()),
|
||||||
syntax_contexts: FxHashMap::default(),
|
syntax_contexts: FxHashMap::default(),
|
||||||
expn_data: FxHashMap::default(),
|
expn_data: UnhashMap::default(),
|
||||||
|
foreign_expn_data: UnhashMap::default(),
|
||||||
hygiene_context: Default::default(),
|
hygiene_context: Default::default(),
|
||||||
foreign_def_path_hashes: Default::default(),
|
foreign_def_path_hashes: Default::default(),
|
||||||
latest_foreign_def_path_hashes: Default::default(),
|
latest_foreign_def_path_hashes: Default::default(),
|
||||||
@ -351,7 +355,8 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut syntax_contexts = FxHashMap::default();
|
let mut syntax_contexts = FxHashMap::default();
|
||||||
let mut expn_ids = FxHashMap::default();
|
let mut expn_data = UnhashMap::default();
|
||||||
|
let mut foreign_expn_data = UnhashMap::default();
|
||||||
|
|
||||||
// Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current
|
// Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current
|
||||||
// session.
|
// session.
|
||||||
@ -364,10 +369,14 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
syntax_contexts.insert(index, pos);
|
syntax_contexts.insert(index, pos);
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
|encoder, index, expn_data, hash| -> FileEncodeResult {
|
|encoder, expn_id, data, hash| -> FileEncodeResult {
|
||||||
let pos = AbsoluteBytePos::new(encoder.position());
|
if expn_id.krate == LOCAL_CRATE {
|
||||||
encoder.encode_tagged(TAG_EXPN_DATA, &(expn_data, hash))?;
|
let pos = AbsoluteBytePos::new(encoder.position());
|
||||||
expn_ids.insert(index, pos);
|
encoder.encode_tagged(TAG_EXPN_DATA, data)?;
|
||||||
|
expn_data.insert(hash, pos);
|
||||||
|
} else {
|
||||||
|
foreign_expn_data.insert(hash, expn_id.local_id.as_u32());
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
@ -385,7 +394,8 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
diagnostics_index,
|
diagnostics_index,
|
||||||
interpret_alloc_index,
|
interpret_alloc_index,
|
||||||
syntax_contexts,
|
syntax_contexts,
|
||||||
expn_data: expn_ids,
|
expn_data,
|
||||||
|
foreign_expn_data,
|
||||||
foreign_def_path_hashes,
|
foreign_def_path_hashes,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
@ -547,6 +557,7 @@ impl<'sess> OnDiskCache<'sess> {
|
|||||||
alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
|
alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
|
||||||
syntax_contexts: &self.syntax_contexts,
|
syntax_contexts: &self.syntax_contexts,
|
||||||
expn_data: &self.expn_data,
|
expn_data: &self.expn_data,
|
||||||
|
foreign_expn_data: &self.foreign_expn_data,
|
||||||
hygiene_context: &self.hygiene_context,
|
hygiene_context: &self.hygiene_context,
|
||||||
};
|
};
|
||||||
f(&mut decoder)
|
f(&mut decoder)
|
||||||
@ -641,7 +652,8 @@ pub struct CacheDecoder<'a, 'tcx> {
|
|||||||
file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
|
file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
|
||||||
alloc_decoding_session: AllocDecodingSession<'a>,
|
alloc_decoding_session: AllocDecodingSession<'a>,
|
||||||
syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
|
syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
|
||||||
expn_data: &'a FxHashMap<u32, AbsoluteBytePos>,
|
expn_data: &'a UnhashMap<ExpnHash, AbsoluteBytePos>,
|
||||||
|
foreign_expn_data: &'a UnhashMap<ExpnHash, u32>,
|
||||||
hygiene_context: &'a HygieneDecodeContext,
|
hygiene_context: &'a HygieneDecodeContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -792,23 +804,43 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
|
|||||||
|
|
||||||
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
|
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
|
||||||
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
|
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
|
||||||
let expn_data = decoder.expn_data;
|
let hash = ExpnHash::decode(decoder)?;
|
||||||
rustc_span::hygiene::decode_expn_id(
|
if hash.is_root() {
|
||||||
decoder,
|
return Ok(ExpnId::root());
|
||||||
ExpnDataDecodeMode::incr_comp(decoder.hygiene_context),
|
}
|
||||||
|this, index| {
|
|
||||||
// This closure is invoked if we haven't already decoded the data for the `ExpnId` we are deserializing.
|
|
||||||
// We look up the position of the associated `ExpnData` and decode it.
|
|
||||||
let pos = expn_data
|
|
||||||
.get(&index)
|
|
||||||
.unwrap_or_else(|| panic!("Bad index {:?} (map {:?})", index, expn_data));
|
|
||||||
|
|
||||||
this.with_position(pos.to_usize(), |decoder| {
|
if let Some(expn_id) = ExpnId::from_hash(hash) {
|
||||||
let data: (ExpnData, ExpnHash) = decode_tagged(decoder, TAG_EXPN_DATA)?;
|
return Ok(expn_id);
|
||||||
Ok(data)
|
}
|
||||||
})
|
|
||||||
},
|
let krate = decoder.cnum_map[&hash.stable_crate_id()];
|
||||||
)
|
|
||||||
|
let expn_id = if krate == LOCAL_CRATE {
|
||||||
|
// We look up the position of the associated `ExpnData` and decode it.
|
||||||
|
let pos = decoder
|
||||||
|
.expn_data
|
||||||
|
.get(&hash)
|
||||||
|
.unwrap_or_else(|| panic!("Bad hash {:?} (map {:?})", hash, decoder.expn_data));
|
||||||
|
|
||||||
|
let data: ExpnData = decoder
|
||||||
|
.with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA))?;
|
||||||
|
rustc_span::hygiene::register_local_expn_id(data, hash)
|
||||||
|
} else {
|
||||||
|
let index_guess = decoder.foreign_expn_data[&hash];
|
||||||
|
decoder.tcx.untracked_resolutions.cstore.expn_hash_to_expn_id(krate, index_guess, hash)
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
|
let mut hcx = decoder.tcx.create_stable_hashing_context();
|
||||||
|
let mut hasher = StableHasher::new();
|
||||||
|
hcx.while_hashing_spans(true, |hcx| expn_id.expn_data().hash_stable(hcx, &mut hasher));
|
||||||
|
let local_hash: u64 = hasher.finish();
|
||||||
|
debug_assert_eq!(hash.local_hash(), local_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(expn_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,12 +1015,8 @@ where
|
|||||||
E: 'a + OpaqueEncoder,
|
E: 'a + OpaqueEncoder,
|
||||||
{
|
{
|
||||||
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
|
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
|
||||||
rustc_span::hygiene::raw_encode_expn_id(
|
s.hygiene_context.schedule_expn_data_for_encoding(*self);
|
||||||
*self,
|
self.expn_hash().encode(s)
|
||||||
s.hygiene_context,
|
|
||||||
ExpnDataEncodeMode::IncrComp,
|
|
||||||
s,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ use rustc_middle::bug;
|
|||||||
use rustc_middle::hir::exports::Export;
|
use rustc_middle::hir::exports::Export;
|
||||||
use rustc_middle::middle::cstore::CrateStore;
|
use rustc_middle::middle::cstore::CrateStore;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_span::hygiene::{ExpnId, MacroKind};
|
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
|
||||||
use rustc_span::source_map::{respan, Spanned};
|
use rustc_span::source_map::{respan, Spanned};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@ -42,7 +42,7 @@ use tracing::debug;
|
|||||||
|
|
||||||
type Res = def::Res<NodeId>;
|
type Res = def::Res<NodeId>;
|
||||||
|
|
||||||
impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, ExpnId) {
|
impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, LocalExpnId) {
|
||||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||||
arenas.alloc_name_binding(NameBinding {
|
arenas.alloc_name_binding(NameBinding {
|
||||||
kind: NameBindingKind::Module(self.0),
|
kind: NameBindingKind::Module(self.0),
|
||||||
@ -54,7 +54,7 @@ impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, ExpnId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId) {
|
impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, LocalExpnId) {
|
||||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||||
arenas.alloc_name_binding(NameBinding {
|
arenas.alloc_name_binding(NameBinding {
|
||||||
kind: NameBindingKind::Res(self.0, false),
|
kind: NameBindingKind::Res(self.0, false),
|
||||||
@ -68,7 +68,7 @@ impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId) {
|
|||||||
|
|
||||||
struct IsMacroExport;
|
struct IsMacroExport;
|
||||||
|
|
||||||
impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId, IsMacroExport) {
|
impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, LocalExpnId, IsMacroExport) {
|
||||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||||
arenas.alloc_name_binding(NameBinding {
|
arenas.alloc_name_binding(NameBinding {
|
||||||
kind: NameBindingKind::Res(self.0, true),
|
kind: NameBindingKind::Res(self.0, true),
|
||||||
@ -157,7 +157,12 @@ impl<'a> Resolver<'a> {
|
|||||||
crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
|
crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
|
||||||
let def_id = match expn_id.expn_data().macro_def_id {
|
let def_id = match expn_id.expn_data().macro_def_id {
|
||||||
Some(def_id) => def_id,
|
Some(def_id) => def_id,
|
||||||
None => return self.ast_transform_scopes.get(&expn_id).unwrap_or(&self.graph_root),
|
None => {
|
||||||
|
return expn_id
|
||||||
|
.as_local()
|
||||||
|
.and_then(|expn_id| self.ast_transform_scopes.get(&expn_id))
|
||||||
|
.unwrap_or(&self.graph_root);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
self.macro_def_scope_from_def_id(def_id)
|
self.macro_def_scope_from_def_id(def_id)
|
||||||
}
|
}
|
||||||
@ -739,7 +744,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||||||
if ptr::eq(parent, self.r.graph_root) {
|
if ptr::eq(parent, self.r.graph_root) {
|
||||||
if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0())
|
if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0())
|
||||||
{
|
{
|
||||||
if expansion != ExpnId::root()
|
if expansion != LocalExpnId::ROOT
|
||||||
&& orig_name.is_some()
|
&& orig_name.is_some()
|
||||||
&& entry.extern_crate_item.is_none()
|
&& entry.extern_crate_item.is_none()
|
||||||
{
|
{
|
||||||
@ -769,7 +774,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||||||
no_implicit_prelude: parent.no_implicit_prelude || {
|
no_implicit_prelude: parent.no_implicit_prelude || {
|
||||||
self.r.session.contains_name(&item.attrs, sym::no_implicit_prelude)
|
self.r.session.contains_name(&item.attrs, sym::no_implicit_prelude)
|
||||||
},
|
},
|
||||||
..ModuleData::new(Some(parent), module_kind, def_id, expansion, item.span)
|
..ModuleData::new(
|
||||||
|
Some(parent),
|
||||||
|
module_kind,
|
||||||
|
def_id,
|
||||||
|
expansion.to_expn_id(),
|
||||||
|
item.span,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||||
self.r.module_map.insert(local_def_id, module);
|
self.r.module_map.insert(local_def_id, module);
|
||||||
@ -808,7 +819,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||||||
parent,
|
parent,
|
||||||
module_kind,
|
module_kind,
|
||||||
parent.nearest_parent_mod,
|
parent.nearest_parent_mod,
|
||||||
expansion,
|
expansion.to_expn_id(),
|
||||||
item.span,
|
item.span,
|
||||||
);
|
);
|
||||||
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||||
@ -883,7 +894,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||||||
parent,
|
parent,
|
||||||
module_kind,
|
module_kind,
|
||||||
parent.nearest_parent_mod,
|
parent.nearest_parent_mod,
|
||||||
expansion,
|
expansion.to_expn_id(),
|
||||||
item.span,
|
item.span,
|
||||||
);
|
);
|
||||||
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||||
@ -926,7 +937,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||||||
parent,
|
parent,
|
||||||
ModuleKind::Block(block.id),
|
ModuleKind::Block(block.id),
|
||||||
parent.nearest_parent_mod,
|
parent.nearest_parent_mod,
|
||||||
expansion,
|
expansion.to_expn_id(),
|
||||||
block.span,
|
block.span,
|
||||||
);
|
);
|
||||||
self.r.block_map.insert(block.id, module);
|
self.r.block_map.insert(block.id, module);
|
||||||
@ -946,7 +957,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||||||
parent,
|
parent,
|
||||||
ModuleKind::Def(kind, def_id, ident.name),
|
ModuleKind::Def(kind, def_id, ident.name),
|
||||||
def_id,
|
def_id,
|
||||||
expansion,
|
expansion.to_expn_id(),
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
self.r.define(parent, ident, TypeNS, (module, vis, span, expansion));
|
self.r.define(parent, ident, TypeNS, (module, vis, span, expansion));
|
||||||
@ -1112,7 +1123,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let allow_shadowing = self.parent_scope.expansion == ExpnId::root();
|
let allow_shadowing = self.parent_scope.expansion == LocalExpnId::ROOT;
|
||||||
if let Some(span) = import_all {
|
if let Some(span) = import_all {
|
||||||
let import = macro_use_import(self, span);
|
let import = macro_use_import(self, span);
|
||||||
self.r.potentially_unused_imports.push(import);
|
self.r.potentially_unused_imports.push(import);
|
||||||
@ -1175,7 +1186,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_invoc(&mut self, id: NodeId) -> ExpnId {
|
fn visit_invoc(&mut self, id: NodeId) -> LocalExpnId {
|
||||||
let invoc_id = id.placeholder_to_expn_id();
|
let invoc_id = id.placeholder_to_expn_id();
|
||||||
let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
|
let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
|
||||||
assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
|
assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
|
||||||
|
@ -6,7 +6,7 @@ use rustc_ast_lowering::ResolverAstLowering;
|
|||||||
use rustc_expand::expand::AstFragment;
|
use rustc_expand::expand::AstFragment;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::definitions::*;
|
use rustc_hir::definitions::*;
|
||||||
use rustc_span::hygiene::ExpnId;
|
use rustc_span::hygiene::LocalExpnId;
|
||||||
use rustc_span::symbol::{kw, sym};
|
use rustc_span::symbol::{kw, sym};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
@ -14,7 +14,7 @@ use tracing::debug;
|
|||||||
crate fn collect_definitions(
|
crate fn collect_definitions(
|
||||||
resolver: &mut Resolver<'_>,
|
resolver: &mut Resolver<'_>,
|
||||||
fragment: &AstFragment,
|
fragment: &AstFragment,
|
||||||
expansion: ExpnId,
|
expansion: LocalExpnId,
|
||||||
) {
|
) {
|
||||||
let (parent_def, impl_trait_context) = resolver.invocation_parents[&expansion];
|
let (parent_def, impl_trait_context) = resolver.invocation_parents[&expansion];
|
||||||
fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion, impl_trait_context });
|
fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion, impl_trait_context });
|
||||||
@ -25,14 +25,14 @@ struct DefCollector<'a, 'b> {
|
|||||||
resolver: &'a mut Resolver<'b>,
|
resolver: &'a mut Resolver<'b>,
|
||||||
parent_def: LocalDefId,
|
parent_def: LocalDefId,
|
||||||
impl_trait_context: ImplTraitContext,
|
impl_trait_context: ImplTraitContext,
|
||||||
expansion: ExpnId,
|
expansion: LocalExpnId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> DefCollector<'a, 'b> {
|
impl<'a, 'b> DefCollector<'a, 'b> {
|
||||||
fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId {
|
fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId {
|
||||||
let parent_def = self.parent_def;
|
let parent_def = self.parent_def;
|
||||||
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
|
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
|
||||||
self.resolver.create_def(parent_def, node_id, data, self.expansion, span)
|
self.resolver.create_def(parent_def, node_id, data, self.expansion.to_expn_id(), span)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
|
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
|
||||||
@ -285,7 +285,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
|
|||||||
item_def,
|
item_def,
|
||||||
node_id,
|
node_id,
|
||||||
DefPathData::ImplTrait,
|
DefPathData::ImplTrait,
|
||||||
self.expansion,
|
self.expansion.to_expn_id(),
|
||||||
ty.span,
|
ty.span,
|
||||||
),
|
),
|
||||||
ImplTraitContext::Existential => {
|
ImplTraitContext::Existential => {
|
||||||
|
@ -22,7 +22,7 @@ use rustc_middle::span_bug;
|
|||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_session::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
|
use rustc_session::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
|
||||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||||
use rustc_span::hygiene::ExpnId;
|
use rustc_span::hygiene::LocalExpnId;
|
||||||
use rustc_span::lev_distance::find_best_match_for_name;
|
use rustc_span::lev_distance::find_best_match_for_name;
|
||||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||||
use rustc_span::{MultiSpan, Span};
|
use rustc_span::{MultiSpan, Span};
|
||||||
@ -237,8 +237,9 @@ impl<'a> Resolver<'a> {
|
|||||||
if ns == TypeNS {
|
if ns == TypeNS {
|
||||||
if ident.name == kw::Crate || ident.name == kw::DollarCrate {
|
if ident.name == kw::Crate || ident.name == kw::DollarCrate {
|
||||||
let module = self.resolve_crate_root(ident);
|
let module = self.resolve_crate_root(ident);
|
||||||
let binding = (module, ty::Visibility::Public, module.span, ExpnId::root())
|
let binding =
|
||||||
.to_name_binding(self.arenas);
|
(module, ty::Visibility::Public, module.span, LocalExpnId::ROOT)
|
||||||
|
.to_name_binding(self.arenas);
|
||||||
return Ok(binding);
|
return Ok(binding);
|
||||||
} else if ident.name == kw::Super || ident.name == kw::SelfLower {
|
} else if ident.name == kw::Super || ident.name == kw::SelfLower {
|
||||||
// FIXME: Implement these with renaming requirements so that e.g.
|
// FIXME: Implement these with renaming requirements so that e.g.
|
||||||
@ -265,7 +266,7 @@ impl<'a> Resolver<'a> {
|
|||||||
self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
|
self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
|
||||||
|
|
||||||
if let Some(binding) = resolution.binding {
|
if let Some(binding) = resolution.binding {
|
||||||
if !restricted_shadowing && binding.expansion != ExpnId::root() {
|
if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT {
|
||||||
if let NameBindingKind::Res(_, true) = binding.kind {
|
if let NameBindingKind::Res(_, true) = binding.kind {
|
||||||
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
|
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
|
||||||
}
|
}
|
||||||
@ -307,7 +308,7 @@ impl<'a> Resolver<'a> {
|
|||||||
if let Some(shadowed_glob) = resolution.shadowed_glob {
|
if let Some(shadowed_glob) = resolution.shadowed_glob {
|
||||||
// Forbid expanded shadowing to avoid time travel.
|
// Forbid expanded shadowing to avoid time travel.
|
||||||
if restricted_shadowing
|
if restricted_shadowing
|
||||||
&& binding.expansion != ExpnId::root()
|
&& binding.expansion != LocalExpnId::ROOT
|
||||||
&& binding.res() != shadowed_glob.res()
|
&& binding.res() != shadowed_glob.res()
|
||||||
{
|
{
|
||||||
self.ambiguity_errors.push(AmbiguityError {
|
self.ambiguity_errors.push(AmbiguityError {
|
||||||
@ -521,7 +522,7 @@ impl<'a> Resolver<'a> {
|
|||||||
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
|
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
|
||||||
if glob_binding.res() != nonglob_binding.res()
|
if glob_binding.res() != nonglob_binding.res()
|
||||||
&& key.ns == MacroNS
|
&& key.ns == MacroNS
|
||||||
&& nonglob_binding.expansion != ExpnId::root()
|
&& nonglob_binding.expansion != LocalExpnId::ROOT
|
||||||
{
|
{
|
||||||
resolution.binding = Some(this.ambiguity(
|
resolution.binding = Some(this.ambiguity(
|
||||||
AmbiguityKind::GlobVsExpanded,
|
AmbiguityKind::GlobVsExpanded,
|
||||||
@ -1271,7 +1272,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
|||||||
target: Ident,
|
target: Ident,
|
||||||
) {
|
) {
|
||||||
// Skip if the import was produced by a macro.
|
// Skip if the import was produced by a macro.
|
||||||
if import.parent_scope.expansion != ExpnId::root() {
|
if import.parent_scope.expansion != LocalExpnId::ROOT {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ use rustc_session::lint;
|
|||||||
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency};
|
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext, Transparency};
|
||||||
use rustc_span::source_map::{CachingSourceMapView, Spanned};
|
use rustc_span::source_map::{CachingSourceMapView, Spanned};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
@ -103,7 +103,7 @@ impl Determinacy {
|
|||||||
/// but not for late resolution yet.
|
/// but not for late resolution yet.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
enum Scope<'a> {
|
enum Scope<'a> {
|
||||||
DeriveHelpers(ExpnId),
|
DeriveHelpers(LocalExpnId),
|
||||||
DeriveHelpersCompat,
|
DeriveHelpersCompat,
|
||||||
MacroRules(MacroRulesScopeRef<'a>),
|
MacroRules(MacroRulesScopeRef<'a>),
|
||||||
CrateRoot,
|
CrateRoot,
|
||||||
@ -143,7 +143,7 @@ enum ScopeSet<'a> {
|
|||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct ParentScope<'a> {
|
pub struct ParentScope<'a> {
|
||||||
module: Module<'a>,
|
module: Module<'a>,
|
||||||
expansion: ExpnId,
|
expansion: LocalExpnId,
|
||||||
macro_rules: MacroRulesScopeRef<'a>,
|
macro_rules: MacroRulesScopeRef<'a>,
|
||||||
derives: &'a [ast::Path],
|
derives: &'a [ast::Path],
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ impl<'a> ParentScope<'a> {
|
|||||||
pub fn module(module: Module<'a>, resolver: &Resolver<'a>) -> ParentScope<'a> {
|
pub fn module(module: Module<'a>, resolver: &Resolver<'a>) -> ParentScope<'a> {
|
||||||
ParentScope {
|
ParentScope {
|
||||||
module,
|
module,
|
||||||
expansion: ExpnId::root(),
|
expansion: LocalExpnId::ROOT,
|
||||||
macro_rules: resolver.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty),
|
macro_rules: resolver.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty),
|
||||||
derives: &[],
|
derives: &[],
|
||||||
}
|
}
|
||||||
@ -515,7 +515,7 @@ pub struct ModuleData<'a> {
|
|||||||
populate_on_access: Cell<bool>,
|
populate_on_access: Cell<bool>,
|
||||||
|
|
||||||
/// Macro invocations that can expand into items in this module.
|
/// Macro invocations that can expand into items in this module.
|
||||||
unexpanded_invocations: RefCell<FxHashSet<ExpnId>>,
|
unexpanded_invocations: RefCell<FxHashSet<LocalExpnId>>,
|
||||||
|
|
||||||
/// Whether `#[no_implicit_prelude]` is active.
|
/// Whether `#[no_implicit_prelude]` is active.
|
||||||
no_implicit_prelude: bool,
|
no_implicit_prelude: bool,
|
||||||
@ -645,7 +645,7 @@ impl<'a> fmt::Debug for ModuleData<'a> {
|
|||||||
pub struct NameBinding<'a> {
|
pub struct NameBinding<'a> {
|
||||||
kind: NameBindingKind<'a>,
|
kind: NameBindingKind<'a>,
|
||||||
ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>,
|
ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>,
|
||||||
expansion: ExpnId,
|
expansion: LocalExpnId,
|
||||||
span: Span,
|
span: Span,
|
||||||
vis: ty::Visibility,
|
vis: ty::Visibility,
|
||||||
}
|
}
|
||||||
@ -829,7 +829,11 @@ impl<'a> NameBinding<'a> {
|
|||||||
// in some later round and screw up our previously found resolution.
|
// in some later round and screw up our previously found resolution.
|
||||||
// See more detailed explanation in
|
// See more detailed explanation in
|
||||||
// https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049
|
// https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049
|
||||||
fn may_appear_after(&self, invoc_parent_expansion: ExpnId, binding: &NameBinding<'_>) -> bool {
|
fn may_appear_after(
|
||||||
|
&self,
|
||||||
|
invoc_parent_expansion: LocalExpnId,
|
||||||
|
binding: &NameBinding<'_>,
|
||||||
|
) -> bool {
|
||||||
// self > max(invoc, binding) => !(self <= invoc || self <= binding)
|
// self > max(invoc, binding) => !(self <= invoc || self <= binding)
|
||||||
// Expansions are partially ordered, so "may appear after" is an inversion of
|
// Expansions are partially ordered, so "may appear after" is an inversion of
|
||||||
// "certainly appears before or simultaneously" and includes unordered cases.
|
// "certainly appears before or simultaneously" and includes unordered cases.
|
||||||
@ -966,7 +970,7 @@ pub struct Resolver<'a> {
|
|||||||
dummy_ext_derive: Lrc<SyntaxExtension>,
|
dummy_ext_derive: Lrc<SyntaxExtension>,
|
||||||
non_macro_attrs: [Lrc<SyntaxExtension>; 2],
|
non_macro_attrs: [Lrc<SyntaxExtension>; 2],
|
||||||
local_macro_def_scopes: FxHashMap<LocalDefId, Module<'a>>,
|
local_macro_def_scopes: FxHashMap<LocalDefId, Module<'a>>,
|
||||||
ast_transform_scopes: FxHashMap<ExpnId, Module<'a>>,
|
ast_transform_scopes: FxHashMap<LocalExpnId, Module<'a>>,
|
||||||
unused_macros: FxHashMap<LocalDefId, (NodeId, Span)>,
|
unused_macros: FxHashMap<LocalDefId, (NodeId, Span)>,
|
||||||
proc_macro_stubs: FxHashSet<LocalDefId>,
|
proc_macro_stubs: FxHashSet<LocalDefId>,
|
||||||
/// Traces collected during macro resolution and validated when it's complete.
|
/// Traces collected during macro resolution and validated when it's complete.
|
||||||
@ -978,18 +982,18 @@ pub struct Resolver<'a> {
|
|||||||
/// `derive(Copy)` marks items they are applied to so they are treated specially later.
|
/// `derive(Copy)` marks items they are applied to so they are treated specially later.
|
||||||
/// Derive macros cannot modify the item themselves and have to store the markers in the global
|
/// Derive macros cannot modify the item themselves and have to store the markers in the global
|
||||||
/// context, so they attach the markers to derive container IDs using this resolver table.
|
/// context, so they attach the markers to derive container IDs using this resolver table.
|
||||||
containers_deriving_copy: FxHashSet<ExpnId>,
|
containers_deriving_copy: FxHashSet<LocalExpnId>,
|
||||||
/// Parent scopes in which the macros were invoked.
|
/// Parent scopes in which the macros were invoked.
|
||||||
/// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere.
|
/// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere.
|
||||||
invocation_parent_scopes: FxHashMap<ExpnId, ParentScope<'a>>,
|
invocation_parent_scopes: FxHashMap<LocalExpnId, ParentScope<'a>>,
|
||||||
/// `macro_rules` scopes *produced* by expanding the macro invocations,
|
/// `macro_rules` scopes *produced* by expanding the macro invocations,
|
||||||
/// include all the `macro_rules` items and other invocations generated by them.
|
/// include all the `macro_rules` items and other invocations generated by them.
|
||||||
output_macro_rules_scopes: FxHashMap<ExpnId, MacroRulesScopeRef<'a>>,
|
output_macro_rules_scopes: FxHashMap<LocalExpnId, MacroRulesScopeRef<'a>>,
|
||||||
/// Helper attributes that are in scope for the given expansion.
|
/// Helper attributes that are in scope for the given expansion.
|
||||||
helper_attrs: FxHashMap<ExpnId, Vec<Ident>>,
|
helper_attrs: FxHashMap<LocalExpnId, Vec<Ident>>,
|
||||||
/// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute
|
/// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute
|
||||||
/// with the given `ExpnId`.
|
/// with the given `ExpnId`.
|
||||||
derive_data: FxHashMap<ExpnId, DeriveData>,
|
derive_data: FxHashMap<LocalExpnId, DeriveData>,
|
||||||
|
|
||||||
/// Avoid duplicated errors for "name already defined".
|
/// Avoid duplicated errors for "name already defined".
|
||||||
name_already_seen: FxHashMap<Symbol, Span>,
|
name_already_seen: FxHashMap<Symbol, Span>,
|
||||||
@ -1018,7 +1022,7 @@ pub struct Resolver<'a> {
|
|||||||
/// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
|
/// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
|
||||||
/// we know what parent node that fragment should be attached to thanks to this table,
|
/// we know what parent node that fragment should be attached to thanks to this table,
|
||||||
/// and how the `impl Trait` fragments were introduced.
|
/// and how the `impl Trait` fragments were introduced.
|
||||||
invocation_parents: FxHashMap<ExpnId, (LocalDefId, ImplTraitContext)>,
|
invocation_parents: FxHashMap<LocalExpnId, (LocalDefId, ImplTraitContext)>,
|
||||||
|
|
||||||
next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>,
|
next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>,
|
||||||
/// Some way to know that we are in a *trait* impl in `visit_assoc_item`.
|
/// Some way to know that we are in a *trait* impl in `visit_assoc_item`.
|
||||||
@ -1268,7 +1272,7 @@ impl<'a> Resolver<'a> {
|
|||||||
node_id_to_def_id.insert(CRATE_NODE_ID, root);
|
node_id_to_def_id.insert(CRATE_NODE_ID, root);
|
||||||
|
|
||||||
let mut invocation_parents = FxHashMap::default();
|
let mut invocation_parents = FxHashMap::default();
|
||||||
invocation_parents.insert(ExpnId::root(), (root, ImplTraitContext::Existential));
|
invocation_parents.insert(LocalExpnId::ROOT, (root, ImplTraitContext::Existential));
|
||||||
|
|
||||||
let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = session
|
let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = session
|
||||||
.opts
|
.opts
|
||||||
@ -1342,7 +1346,7 @@ impl<'a> Resolver<'a> {
|
|||||||
dummy_binding: arenas.alloc_name_binding(NameBinding {
|
dummy_binding: arenas.alloc_name_binding(NameBinding {
|
||||||
kind: NameBindingKind::Res(Res::Err, false),
|
kind: NameBindingKind::Res(Res::Err, false),
|
||||||
ambiguity: None,
|
ambiguity: None,
|
||||||
expansion: ExpnId::root(),
|
expansion: LocalExpnId::ROOT,
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
vis: ty::Visibility::Public,
|
vis: ty::Visibility::Public,
|
||||||
}),
|
}),
|
||||||
@ -1392,7 +1396,7 @@ impl<'a> Resolver<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let root_parent_scope = ParentScope::module(graph_root, &resolver);
|
let root_parent_scope = ParentScope::module(graph_root, &resolver);
|
||||||
resolver.invocation_parent_scopes.insert(ExpnId::root(), root_parent_scope);
|
resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope);
|
||||||
|
|
||||||
resolver
|
resolver
|
||||||
}
|
}
|
||||||
@ -1810,7 +1814,8 @@ impl<'a> Resolver<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scope = match scope {
|
scope = match scope {
|
||||||
Scope::DeriveHelpers(expn_id) if expn_id != ExpnId::root() => {
|
Scope::DeriveHelpers(LocalExpnId::ROOT) => Scope::DeriveHelpersCompat,
|
||||||
|
Scope::DeriveHelpers(expn_id) => {
|
||||||
// Derive helpers are not visible to code generated by bang or derive macros.
|
// Derive helpers are not visible to code generated by bang or derive macros.
|
||||||
let expn_data = expn_id.expn_data();
|
let expn_data = expn_id.expn_data();
|
||||||
match expn_data.kind {
|
match expn_data.kind {
|
||||||
@ -1818,10 +1823,9 @@ impl<'a> Resolver<'a> {
|
|||||||
| ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
|
| ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
|
||||||
Scope::DeriveHelpersCompat
|
Scope::DeriveHelpersCompat
|
||||||
}
|
}
|
||||||
_ => Scope::DeriveHelpers(expn_data.parent),
|
_ => Scope::DeriveHelpers(expn_data.parent.expect_local()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat,
|
|
||||||
Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules),
|
Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules),
|
||||||
Scope::MacroRules(macro_rules_scope) => match macro_rules_scope.get() {
|
Scope::MacroRules(macro_rules_scope) => match macro_rules_scope.get() {
|
||||||
MacroRulesScope::Binding(binding) => {
|
MacroRulesScope::Binding(binding) => {
|
||||||
@ -3248,7 +3252,7 @@ impl<'a> Resolver<'a> {
|
|||||||
};
|
};
|
||||||
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
|
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
|
||||||
Some(
|
Some(
|
||||||
(crate_root, ty::Visibility::Public, DUMMY_SP, ExpnId::root())
|
(crate_root, ty::Visibility::Public, DUMMY_SP, LocalExpnId::ROOT)
|
||||||
.to_name_binding(self.arenas),
|
.to_name_binding(self.arenas),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ use rustc_session::lint::BuiltinLintDiagnostics;
|
|||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind};
|
use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId};
|
||||||
use rustc_span::hygiene::{AstPass, MacroKind};
|
use rustc_span::hygiene::{AstPass, MacroKind};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
@ -62,7 +62,7 @@ pub enum MacroRulesScope<'a> {
|
|||||||
Binding(&'a MacroRulesBinding<'a>),
|
Binding(&'a MacroRulesBinding<'a>),
|
||||||
/// The scope introduced by a macro invocation that can potentially
|
/// The scope introduced by a macro invocation that can potentially
|
||||||
/// create a `macro_rules!` macro definition.
|
/// create a `macro_rules!` macro definition.
|
||||||
Invocation(ExpnId),
|
Invocation(LocalExpnId),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `macro_rules!` scopes are always kept by reference and inside a cell.
|
/// `macro_rules!` scopes are always kept by reference and inside a cell.
|
||||||
@ -190,7 +190,11 @@ impl<'a> ResolverExpand for Resolver<'a> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ast_fragment_with_placeholders(&mut self, expansion: ExpnId, fragment: &AstFragment) {
|
fn visit_ast_fragment_with_placeholders(
|
||||||
|
&mut self,
|
||||||
|
expansion: LocalExpnId,
|
||||||
|
fragment: &AstFragment,
|
||||||
|
) {
|
||||||
// Integrate the new AST fragment into all the definition and module structures.
|
// Integrate the new AST fragment into all the definition and module structures.
|
||||||
// We are inside the `expansion` now, but other parent scope components are still the same.
|
// We are inside the `expansion` now, but other parent scope components are still the same.
|
||||||
let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] };
|
let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] };
|
||||||
@ -216,9 +220,9 @@ impl<'a> ResolverExpand for Resolver<'a> {
|
|||||||
pass: AstPass,
|
pass: AstPass,
|
||||||
features: &[Symbol],
|
features: &[Symbol],
|
||||||
parent_module_id: Option<NodeId>,
|
parent_module_id: Option<NodeId>,
|
||||||
) -> ExpnId {
|
) -> LocalExpnId {
|
||||||
let parent_module = parent_module_id.map(|module_id| self.local_def_id(module_id));
|
let parent_module = parent_module_id.map(|module_id| self.local_def_id(module_id));
|
||||||
let expn_id = ExpnId::fresh(
|
let expn_id = LocalExpnId::fresh(
|
||||||
ExpnData::allow_unstable(
|
ExpnData::allow_unstable(
|
||||||
ExpnKind::AstPass(pass),
|
ExpnKind::AstPass(pass),
|
||||||
call_site,
|
call_site,
|
||||||
@ -244,7 +248,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
|
|||||||
fn resolve_macro_invocation(
|
fn resolve_macro_invocation(
|
||||||
&mut self,
|
&mut self,
|
||||||
invoc: &Invocation,
|
invoc: &Invocation,
|
||||||
eager_expansion_root: ExpnId,
|
eager_expansion_root: LocalExpnId,
|
||||||
force: bool,
|
force: bool,
|
||||||
) -> Result<Lrc<SyntaxExtension>, Indeterminate> {
|
) -> Result<Lrc<SyntaxExtension>, Indeterminate> {
|
||||||
let invoc_id = invoc.expansion_data.id;
|
let invoc_id = invoc.expansion_data.id;
|
||||||
@ -328,7 +332,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
|
|||||||
| ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
|
| ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_ => expn_id = expn_data.parent,
|
_ => expn_id = expn_data.parent.expect_local(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -344,7 +348,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lint_node_id(&self, expn_id: ExpnId) -> NodeId {
|
fn lint_node_id(&self, expn_id: LocalExpnId) -> NodeId {
|
||||||
// FIXME - make this more precise. This currently returns the NodeId of the
|
// FIXME - make this more precise. This currently returns the NodeId of the
|
||||||
// nearest closing item - we should try to return the closest parent of the ExpnId
|
// nearest closing item - we should try to return the closest parent of the ExpnId
|
||||||
self.invocation_parents
|
self.invocation_parents
|
||||||
@ -352,13 +356,13 @@ impl<'a> ResolverExpand for Resolver<'a> {
|
|||||||
.map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0])
|
.map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_derive_copy(&self, expn_id: ExpnId) -> bool {
|
fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool {
|
||||||
self.containers_deriving_copy.contains(&expn_id)
|
self.containers_deriving_copy.contains(&expn_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_derives(
|
fn resolve_derives(
|
||||||
&mut self,
|
&mut self,
|
||||||
expn_id: ExpnId,
|
expn_id: LocalExpnId,
|
||||||
force: bool,
|
force: bool,
|
||||||
derive_paths: &dyn Fn() -> DeriveResolutions,
|
derive_paths: &dyn Fn() -> DeriveResolutions,
|
||||||
) -> Result<(), Indeterminate> {
|
) -> Result<(), Indeterminate> {
|
||||||
@ -423,7 +427,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take_derive_resolutions(&mut self, expn_id: ExpnId) -> Option<DeriveResolutions> {
|
fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option<DeriveResolutions> {
|
||||||
self.derive_data.remove(&expn_id).map(|data| data.resolutions)
|
self.derive_data.remove(&expn_id).map(|data| data.resolutions)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,7 +435,11 @@ impl<'a> ResolverExpand for Resolver<'a> {
|
|||||||
// Returns true if the path can certainly be resolved in one of three namespaces,
|
// Returns true if the path can certainly be resolved in one of three namespaces,
|
||||||
// returns false if the path certainly cannot be resolved in any of the three namespaces.
|
// returns false if the path certainly cannot be resolved in any of the three namespaces.
|
||||||
// Returns `Indeterminate` if we cannot give a certain answer yet.
|
// Returns `Indeterminate` if we cannot give a certain answer yet.
|
||||||
fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate> {
|
fn cfg_accessible(
|
||||||
|
&mut self,
|
||||||
|
expn_id: LocalExpnId,
|
||||||
|
path: &ast::Path,
|
||||||
|
) -> Result<bool, Indeterminate> {
|
||||||
let span = path.span;
|
let span = path.span;
|
||||||
let path = &Segment::from_path(path);
|
let path = &Segment::from_path(path);
|
||||||
let parent_scope = self.invocation_parent_scopes[&expn_id];
|
let parent_scope = self.invocation_parent_scopes[&expn_id];
|
||||||
@ -714,7 +722,8 @@ impl<'a> Resolver<'a> {
|
|||||||
let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
|
let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
|
||||||
let ok = |res, span, arenas| {
|
let ok = |res, span, arenas| {
|
||||||
Ok((
|
Ok((
|
||||||
(res, ty::Visibility::Public, span, ExpnId::root()).to_name_binding(arenas),
|
(res, ty::Visibility::Public, span, LocalExpnId::ROOT)
|
||||||
|
.to_name_binding(arenas),
|
||||||
Flags::empty(),
|
Flags::empty(),
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
@ -136,7 +136,7 @@ impl Borrow<Fingerprint> for DefPathHash {
|
|||||||
/// further trouble.
|
/// further trouble.
|
||||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||||
#[derive(HashStable_Generic, Encodable, Decodable)]
|
#[derive(HashStable_Generic, Encodable, Decodable)]
|
||||||
pub struct StableCrateId(u64);
|
pub struct StableCrateId(pub(crate) u64);
|
||||||
|
|
||||||
impl StableCrateId {
|
impl StableCrateId {
|
||||||
pub fn to_u64(self) -> u64 {
|
pub fn to_u64(self) -> u64 {
|
||||||
|
@ -29,12 +29,13 @@ use crate::symbol::{kw, sym, Symbol};
|
|||||||
use crate::with_session_globals;
|
use crate::with_session_globals;
|
||||||
use crate::{HashStableContext, Span, DUMMY_SP};
|
use crate::{HashStableContext, Span, DUMMY_SP};
|
||||||
|
|
||||||
use crate::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::sync::{Lock, Lrc};
|
use rustc_data_structures::sync::{Lock, Lrc};
|
||||||
use rustc_data_structures::unhash::UnhashMap;
|
use rustc_data_structures::unhash::UnhashMap;
|
||||||
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -58,14 +59,67 @@ pub struct SyntaxContextData {
|
|||||||
dollar_crate_name: Symbol,
|
dollar_crate_name: Symbol,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rustc_index::newtype_index! {
|
||||||
|
/// A unique ID associated with a macro invocation and expansion.
|
||||||
|
pub struct ExpnIndex {
|
||||||
|
ENCODABLE = custom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A unique ID associated with a macro invocation and expansion.
|
/// A unique ID associated with a macro invocation and expansion.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ExpnId(u32);
|
pub struct ExpnId {
|
||||||
|
pub krate: CrateNum,
|
||||||
|
pub local_id: ExpnIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for ExpnId {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
// Generate crate_::{{expn_}}.
|
||||||
|
write!(f, "{:?}::{{{{expn{}}}}}", self.krate, self.local_id.private)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rustc_index::newtype_index! {
|
||||||
|
/// A unique ID associated with a macro invocation and expansion.
|
||||||
|
pub struct LocalExpnId {
|
||||||
|
ENCODABLE = custom
|
||||||
|
DEBUG_FORMAT = "expn{}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A unique hash value associated to an expansion.
|
/// A unique hash value associated to an expansion.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
|
||||||
pub struct ExpnHash(Fingerprint);
|
pub struct ExpnHash(Fingerprint);
|
||||||
|
|
||||||
|
impl ExpnHash {
|
||||||
|
/// Returns the [StableCrateId] identifying the crate this [ExpnHash]
|
||||||
|
/// originates from.
|
||||||
|
#[inline]
|
||||||
|
pub fn stable_crate_id(self) -> StableCrateId {
|
||||||
|
StableCrateId(self.0.as_value().0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the crate-local part of the [ExpnHash].
|
||||||
|
///
|
||||||
|
/// Used for tests.
|
||||||
|
#[inline]
|
||||||
|
pub fn local_hash(self) -> u64 {
|
||||||
|
self.0.as_value().1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_root(self) -> bool {
|
||||||
|
self.0 == Fingerprint::ZERO
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds a new [ExpnHash] with the given [StableCrateId] and
|
||||||
|
/// `local_hash`, where `local_hash` must be unique within its crate.
|
||||||
|
fn new(stable_crate_id: StableCrateId, local_hash: u64) -> ExpnHash {
|
||||||
|
ExpnHash(Fingerprint::new(stable_crate_id.0, local_hash))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A property of a macro expansion that determines how identifiers
|
/// A property of a macro expansion that determines how identifiers
|
||||||
/// produced by that expansion are resolved.
|
/// produced by that expansion are resolved.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Encodable, Decodable)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Encodable, Decodable)]
|
||||||
@ -86,31 +140,102 @@ pub enum Transparency {
|
|||||||
Opaque,
|
Opaque,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExpnId {
|
impl LocalExpnId {
|
||||||
pub fn fresh_empty() -> Self {
|
|
||||||
HygieneData::with(|data| data.fresh_expn(None))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fresh(expn_data: ExpnData, ctx: impl HashStableContext) -> Self {
|
|
||||||
let expn_id = HygieneData::with(|data| data.fresh_expn(Some(expn_data)));
|
|
||||||
update_disambiguator(expn_id, ctx);
|
|
||||||
expn_id
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST.
|
/// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST.
|
||||||
#[inline]
|
pub const ROOT: LocalExpnId = LocalExpnId::from_u32(0);
|
||||||
pub fn root() -> Self {
|
|
||||||
ExpnId(0)
|
pub fn from_raw(idx: ExpnIndex) -> LocalExpnId {
|
||||||
|
LocalExpnId::from_u32(idx.as_u32())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_raw(self) -> ExpnIndex {
|
||||||
|
ExpnIndex::from_u32(self.as_u32())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fresh_empty() -> LocalExpnId {
|
||||||
|
HygieneData::with(|data| {
|
||||||
|
let expn_id = data.local_expn_data.push(None);
|
||||||
|
let _eid = data.local_expn_hashes.push(ExpnHash(Fingerprint::ZERO));
|
||||||
|
debug_assert_eq!(expn_id, _eid);
|
||||||
|
expn_id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fresh(mut expn_data: ExpnData, ctx: impl HashStableContext) -> LocalExpnId {
|
||||||
|
debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE);
|
||||||
|
let expn_hash = update_disambiguator(&mut expn_data, ctx);
|
||||||
|
HygieneData::with(|data| {
|
||||||
|
let expn_id = data.local_expn_data.push(Some(expn_data));
|
||||||
|
let _eid = data.local_expn_hashes.push(expn_hash);
|
||||||
|
debug_assert_eq!(expn_id, _eid);
|
||||||
|
let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, expn_id.to_expn_id());
|
||||||
|
debug_assert!(_old_id.is_none());
|
||||||
|
expn_id
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_u32(self) -> u32 {
|
pub fn expn_hash(self) -> ExpnHash {
|
||||||
self.0
|
HygieneData::with(|data| data.local_expn_hash(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_u32(raw: u32) -> ExpnId {
|
pub fn expn_data(self) -> ExpnData {
|
||||||
ExpnId(raw)
|
HygieneData::with(|data| data.local_expn_data(self).clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn to_expn_id(self) -> ExpnId {
|
||||||
|
ExpnId { krate: LOCAL_CRATE, local_id: self.as_raw() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_expn_data(self, mut expn_data: ExpnData, ctx: impl HashStableContext) {
|
||||||
|
debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE);
|
||||||
|
let expn_hash = update_disambiguator(&mut expn_data, ctx);
|
||||||
|
HygieneData::with(|data| {
|
||||||
|
let old_expn_data = &mut data.local_expn_data[self];
|
||||||
|
assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID");
|
||||||
|
*old_expn_data = Some(expn_data);
|
||||||
|
debug_assert_eq!(data.local_expn_hashes[self].0, Fingerprint::ZERO);
|
||||||
|
data.local_expn_hashes[self] = expn_hash;
|
||||||
|
let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, self.to_expn_id());
|
||||||
|
debug_assert!(_old_id.is_none());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_descendant_of(self, ancestor: LocalExpnId) -> bool {
|
||||||
|
self.to_expn_id().is_descendant_of(ancestor.to_expn_id())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than
|
||||||
|
/// `expn_id.is_descendant_of(ctxt.outer_expn())`.
|
||||||
|
#[inline]
|
||||||
|
pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
|
||||||
|
self.to_expn_id().outer_expn_is_descendant_of(ctxt)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns span for the macro which originally caused this expansion to happen.
|
||||||
|
///
|
||||||
|
/// Stops backtracing at include! boundary.
|
||||||
|
#[inline]
|
||||||
|
pub fn expansion_cause(self) -> Option<Span> {
|
||||||
|
self.to_expn_id().expansion_cause()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[track_caller]
|
||||||
|
pub fn parent(self) -> LocalExpnId {
|
||||||
|
self.expn_data().parent.as_local().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExpnId {
|
||||||
|
/// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST.
|
||||||
|
/// Invariant: we do not create any ExpnId with local_id == 0 and krate != 0.
|
||||||
|
pub const fn root() -> ExpnId {
|
||||||
|
ExpnId { krate: LOCAL_CRATE, local_id: ExpnIndex::from_u32(0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -124,20 +249,19 @@ impl ExpnId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn expn_data(self) -> ExpnData {
|
pub fn as_local(self) -> Option<LocalExpnId> {
|
||||||
HygieneData::with(|data| data.expn_data(self).clone())
|
if self.krate == LOCAL_CRATE { Some(LocalExpnId::from_raw(self.local_id)) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_expn_data(self, mut expn_data: ExpnData, ctx: impl HashStableContext) {
|
#[track_caller]
|
||||||
HygieneData::with(|data| {
|
pub fn expect_local(self) -> LocalExpnId {
|
||||||
let old_expn_data = &mut data.expn_data[self.0 as usize];
|
self.as_local().unwrap()
|
||||||
assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID");
|
}
|
||||||
assert_eq!(expn_data.orig_id, None);
|
|
||||||
expn_data.orig_id = Some(self.as_u32());
|
#[inline]
|
||||||
*old_expn_data = Some(expn_data);
|
pub fn expn_data(self) -> ExpnData {
|
||||||
});
|
HygieneData::with(|data| data.expn_data(self).clone())
|
||||||
update_disambiguator(self, ctx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_descendant_of(self, ancestor: ExpnId) -> bool {
|
pub fn is_descendant_of(self, ancestor: ExpnId) -> bool {
|
||||||
@ -175,34 +299,39 @@ pub struct HygieneData {
|
|||||||
/// Each expansion should have an associated expansion data, but sometimes there's a delay
|
/// Each expansion should have an associated expansion data, but sometimes there's a delay
|
||||||
/// between creation of an expansion ID and obtaining its data (e.g. macros are collected
|
/// between creation of an expansion ID and obtaining its data (e.g. macros are collected
|
||||||
/// first and then resolved later), so we use an `Option` here.
|
/// first and then resolved later), so we use an `Option` here.
|
||||||
expn_data: Vec<Option<ExpnData>>,
|
local_expn_data: IndexVec<LocalExpnId, Option<ExpnData>>,
|
||||||
expn_hashes: Vec<ExpnHash>,
|
local_expn_hashes: IndexVec<LocalExpnId, ExpnHash>,
|
||||||
|
/// Data and hash information from external crates. We may eventually want to remove these
|
||||||
|
/// maps, and fetch the information directly from the other crate's metadata like DefIds do.
|
||||||
|
foreign_expn_data: FxHashMap<ExpnId, ExpnData>,
|
||||||
|
foreign_expn_hashes: FxHashMap<ExpnId, ExpnHash>,
|
||||||
expn_hash_to_expn_id: UnhashMap<ExpnHash, ExpnId>,
|
expn_hash_to_expn_id: UnhashMap<ExpnHash, ExpnId>,
|
||||||
syntax_context_data: Vec<SyntaxContextData>,
|
syntax_context_data: Vec<SyntaxContextData>,
|
||||||
syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>,
|
syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>,
|
||||||
/// Maps the `Fingerprint` of an `ExpnData` to the next disambiguator value.
|
/// Maps the `local_hash` of an `ExpnData` to the next disambiguator value.
|
||||||
/// This is used by `update_disambiguator` to keep track of which `ExpnData`s
|
/// This is used by `update_disambiguator` to keep track of which `ExpnData`s
|
||||||
/// would have collisions without a disambiguator.
|
/// would have collisions without a disambiguator.
|
||||||
/// The keys of this map are always computed with `ExpnData.disambiguator`
|
/// The keys of this map are always computed with `ExpnData.disambiguator`
|
||||||
/// set to 0.
|
/// set to 0.
|
||||||
expn_data_disambiguators: FxHashMap<Fingerprint, u32>,
|
expn_data_disambiguators: FxHashMap<u64, u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HygieneData {
|
impl HygieneData {
|
||||||
crate fn new(edition: Edition) -> Self {
|
crate fn new(edition: Edition) -> Self {
|
||||||
let mut root_data = ExpnData::default(
|
let root_data = ExpnData::default(
|
||||||
ExpnKind::Root,
|
ExpnKind::Root,
|
||||||
DUMMY_SP,
|
DUMMY_SP,
|
||||||
edition,
|
edition,
|
||||||
Some(DefId::local(CRATE_DEF_INDEX)),
|
Some(CRATE_DEF_ID.to_def_id()),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
root_data.orig_id = Some(0);
|
|
||||||
|
|
||||||
HygieneData {
|
HygieneData {
|
||||||
expn_data: vec![Some(root_data)],
|
local_expn_data: IndexVec::from_elem_n(Some(root_data), 1),
|
||||||
expn_hashes: vec![ExpnHash(Fingerprint::ZERO)],
|
local_expn_hashes: IndexVec::from_elem_n(ExpnHash(Fingerprint::ZERO), 1),
|
||||||
expn_hash_to_expn_id: std::iter::once((ExpnHash(Fingerprint::ZERO), ExpnId(0)))
|
foreign_expn_data: FxHashMap::default(),
|
||||||
|
foreign_expn_hashes: FxHashMap::default(),
|
||||||
|
expn_hash_to_expn_id: std::iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root()))
|
||||||
.collect(),
|
.collect(),
|
||||||
syntax_context_data: vec![SyntaxContextData {
|
syntax_context_data: vec![SyntaxContextData {
|
||||||
outer_expn: ExpnId::root(),
|
outer_expn: ExpnId::root(),
|
||||||
@ -221,24 +350,29 @@ impl HygieneData {
|
|||||||
with_session_globals(|session_globals| f(&mut *session_globals.hygiene_data.borrow_mut()))
|
with_session_globals(|session_globals| f(&mut *session_globals.hygiene_data.borrow_mut()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fresh_expn(&mut self, mut expn_data: Option<ExpnData>) -> ExpnId {
|
#[inline]
|
||||||
let raw_id = self.expn_data.len() as u32;
|
fn local_expn_hash(&self, expn_id: LocalExpnId) -> ExpnHash {
|
||||||
if let Some(data) = expn_data.as_mut() {
|
self.local_expn_hashes[expn_id]
|
||||||
assert_eq!(data.orig_id, None);
|
|
||||||
data.orig_id = Some(raw_id);
|
|
||||||
}
|
|
||||||
self.expn_data.push(expn_data);
|
|
||||||
self.expn_hashes.push(ExpnHash(Fingerprint::ZERO));
|
|
||||||
ExpnId(raw_id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn expn_hash(&self, expn_id: ExpnId) -> ExpnHash {
|
fn expn_hash(&self, expn_id: ExpnId) -> ExpnHash {
|
||||||
self.expn_hashes[expn_id.0 as usize]
|
match expn_id.as_local() {
|
||||||
|
Some(expn_id) => self.local_expn_hashes[expn_id],
|
||||||
|
None => self.foreign_expn_hashes[&expn_id],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn local_expn_data(&self, expn_id: LocalExpnId) -> &ExpnData {
|
||||||
|
self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expn_data(&self, expn_id: ExpnId) -> &ExpnData {
|
fn expn_data(&self, expn_id: ExpnId) -> &ExpnData {
|
||||||
self.expn_data[expn_id.0 as usize].as_ref().expect("no expansion data for an expansion ID")
|
if let Some(expn_id) = expn_id.as_local() {
|
||||||
|
self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
|
||||||
|
} else {
|
||||||
|
&self.foreign_expn_data[&expn_id]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool {
|
fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool {
|
||||||
@ -453,17 +587,21 @@ pub fn debug_hygiene_data(verbose: bool) -> String {
|
|||||||
} else {
|
} else {
|
||||||
let mut s = String::from("");
|
let mut s = String::from("");
|
||||||
s.push_str("Expansions:");
|
s.push_str("Expansions:");
|
||||||
data.expn_data.iter().enumerate().for_each(|(id, expn_info)| {
|
let mut debug_expn_data = |(id, expn_data): (&ExpnId, &ExpnData)| {
|
||||||
let expn_info = expn_info.as_ref().expect("no expansion data for an expansion ID");
|
|
||||||
s.push_str(&format!(
|
s.push_str(&format!(
|
||||||
"\n{}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}",
|
"\n{:?}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}",
|
||||||
id,
|
id,
|
||||||
expn_info.parent,
|
expn_data.parent,
|
||||||
expn_info.call_site.ctxt(),
|
expn_data.call_site.ctxt(),
|
||||||
expn_info.def_site.ctxt(),
|
expn_data.def_site.ctxt(),
|
||||||
expn_info.kind,
|
expn_data.kind,
|
||||||
));
|
))
|
||||||
|
};
|
||||||
|
data.local_expn_data.iter_enumerated().for_each(|(id, expn_data)| {
|
||||||
|
let expn_data = expn_data.as_ref().expect("no expansion data for an expansion ID");
|
||||||
|
debug_expn_data((&id.to_expn_id(), expn_data))
|
||||||
});
|
});
|
||||||
|
data.foreign_expn_data.iter().for_each(debug_expn_data);
|
||||||
s.push_str("\n\nSyntaxContexts:");
|
s.push_str("\n\nSyntaxContexts:");
|
||||||
data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| {
|
data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| {
|
||||||
s.push_str(&format!(
|
s.push_str(&format!(
|
||||||
@ -696,7 +834,7 @@ impl Span {
|
|||||||
transparency: Transparency,
|
transparency: Transparency,
|
||||||
ctx: impl HashStableContext,
|
ctx: impl HashStableContext,
|
||||||
) -> Span {
|
) -> Span {
|
||||||
let expn_id = ExpnId::fresh(expn_data, ctx);
|
let expn_id = LocalExpnId::fresh(expn_data, ctx).to_expn_id();
|
||||||
HygieneData::with(|data| {
|
HygieneData::with(|data| {
|
||||||
self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id, transparency))
|
self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id, transparency))
|
||||||
})
|
})
|
||||||
@ -738,20 +876,6 @@ pub struct ExpnData {
|
|||||||
/// call_site span would have its own ExpnData, with the call_site
|
/// call_site span would have its own ExpnData, with the call_site
|
||||||
/// pointing to the `foo!` invocation.
|
/// pointing to the `foo!` invocation.
|
||||||
pub call_site: Span,
|
pub call_site: Span,
|
||||||
/// The crate that originally created this `ExpnData`. During
|
|
||||||
/// metadata serialization, we only encode `ExpnData`s that were
|
|
||||||
/// created locally - when our serialized metadata is decoded,
|
|
||||||
/// foreign `ExpnId`s will have their `ExpnData` looked up
|
|
||||||
/// from the crate specified by `Crate
|
|
||||||
krate: CrateNum,
|
|
||||||
/// The raw that this `ExpnData` had in its original crate.
|
|
||||||
/// An `ExpnData` can be created before being assigned an `ExpnId`,
|
|
||||||
/// so this might be `None` until `set_expn_data` is called
|
|
||||||
// This is used only for serialization/deserialization purposes:
|
|
||||||
// two `ExpnData`s that differ only in their `orig_id` should
|
|
||||||
// be considered equivalent.
|
|
||||||
#[stable_hasher(ignore)]
|
|
||||||
orig_id: Option<u32>,
|
|
||||||
/// Used to force two `ExpnData`s to have different `Fingerprint`s.
|
/// Used to force two `ExpnData`s to have different `Fingerprint`s.
|
||||||
/// Due to macro expansion, it's possible to end up with two `ExpnId`s
|
/// Due to macro expansion, it's possible to end up with two `ExpnId`s
|
||||||
/// that have identical `ExpnData`s. This violates the contract of `HashStable`
|
/// that have identical `ExpnData`s. This violates the contract of `HashStable`
|
||||||
@ -790,7 +914,6 @@ pub struct ExpnData {
|
|||||||
pub parent_module: Option<DefId>,
|
pub parent_module: Option<DefId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// These would require special handling of `orig_id`.
|
|
||||||
impl !PartialEq for ExpnData {}
|
impl !PartialEq for ExpnData {}
|
||||||
impl !Hash for ExpnData {}
|
impl !Hash for ExpnData {}
|
||||||
|
|
||||||
@ -818,8 +941,6 @@ impl ExpnData {
|
|||||||
edition,
|
edition,
|
||||||
macro_def_id,
|
macro_def_id,
|
||||||
parent_module,
|
parent_module,
|
||||||
krate: LOCAL_CRATE,
|
|
||||||
orig_id: None,
|
|
||||||
disambiguator: 0,
|
disambiguator: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -843,8 +964,6 @@ impl ExpnData {
|
|||||||
edition,
|
edition,
|
||||||
macro_def_id,
|
macro_def_id,
|
||||||
parent_module,
|
parent_module,
|
||||||
krate: LOCAL_CRATE,
|
|
||||||
orig_id: None,
|
|
||||||
disambiguator: 0,
|
disambiguator: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -869,7 +988,7 @@ impl ExpnData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash_expn(&self, ctx: &mut impl HashStableContext) -> Fingerprint {
|
fn hash_expn(&self, ctx: &mut impl HashStableContext) -> u64 {
|
||||||
let mut hasher = StableHasher::new();
|
let mut hasher = StableHasher::new();
|
||||||
self.hash_stable(ctx, &mut hasher);
|
self.hash_stable(ctx, &mut hasher);
|
||||||
hasher.finish()
|
hasher.finish()
|
||||||
@ -1020,11 +1139,18 @@ pub struct HygieneEncodeContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl HygieneEncodeContext {
|
impl HygieneEncodeContext {
|
||||||
|
/// Record the fact that we need to serialize the corresponding `ExpnData`.
|
||||||
|
pub fn schedule_expn_data_for_encoding(&self, expn: ExpnId) {
|
||||||
|
if !self.serialized_expns.lock().contains(&expn) {
|
||||||
|
self.latest_expns.lock().insert(expn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn encode<T, R>(
|
pub fn encode<T, R>(
|
||||||
&self,
|
&self,
|
||||||
encoder: &mut T,
|
encoder: &mut T,
|
||||||
mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData) -> Result<(), R>,
|
mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData) -> Result<(), R>,
|
||||||
mut encode_expn: impl FnMut(&mut T, u32, ExpnData, ExpnHash) -> Result<(), R>,
|
mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash) -> Result<(), R>,
|
||||||
) -> Result<(), R> {
|
) -> Result<(), R> {
|
||||||
// When we serialize a `SyntaxContextData`, we may end up serializing
|
// When we serialize a `SyntaxContextData`, we may end up serializing
|
||||||
// a `SyntaxContext` that we haven't seen before
|
// a `SyntaxContext` that we haven't seen before
|
||||||
@ -1051,9 +1177,9 @@ impl HygieneEncodeContext {
|
|||||||
|
|
||||||
let latest_expns = { std::mem::take(&mut *self.latest_expns.lock()) };
|
let latest_expns = { std::mem::take(&mut *self.latest_expns.lock()) };
|
||||||
|
|
||||||
for_all_expns_in(latest_expns.into_iter(), |index, expn, data, hash| {
|
for_all_expns_in(latest_expns.into_iter(), |expn, data, hash| {
|
||||||
if self.serialized_expns.lock().insert(expn) {
|
if self.serialized_expns.lock().insert(expn) {
|
||||||
encode_expn(encoder, index, data, hash)?;
|
encode_expn(encoder, expn, data, hash)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
@ -1072,78 +1198,70 @@ pub struct HygieneDecodeContext {
|
|||||||
// so that multiple occurrences of the same serialized id are decoded to the same
|
// so that multiple occurrences of the same serialized id are decoded to the same
|
||||||
// `SyntaxContext`
|
// `SyntaxContext`
|
||||||
remapped_ctxts: Lock<Vec<Option<SyntaxContext>>>,
|
remapped_ctxts: Lock<Vec<Option<SyntaxContext>>>,
|
||||||
// The same as `remapepd_ctxts`, but for `ExpnId`s
|
|
||||||
remapped_expns: Lock<Vec<Option<ExpnId>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_expn_id<'a, D: Decoder, G>(
|
/// Register an expansion which has been decoded from the on-disk-cache for the local crate.
|
||||||
d: &mut D,
|
pub fn register_local_expn_id(data: ExpnData, hash: ExpnHash) -> ExpnId {
|
||||||
mode: ExpnDataDecodeMode<'a, G>,
|
HygieneData::with(|hygiene_data| {
|
||||||
decode_data: impl FnOnce(&mut D, u32) -> Result<(ExpnData, ExpnHash), D::Error>,
|
let expn_id = hygiene_data.local_expn_data.next_index();
|
||||||
) -> Result<ExpnId, D::Error>
|
hygiene_data.local_expn_data.push(Some(data));
|
||||||
where
|
let _eid = hygiene_data.local_expn_hashes.push(hash);
|
||||||
G: FnOnce(CrateNum) -> &'a HygieneDecodeContext,
|
debug_assert_eq!(expn_id, _eid);
|
||||||
{
|
|
||||||
let index = u32::decode(d)?;
|
|
||||||
let context = match mode {
|
|
||||||
ExpnDataDecodeMode::IncrComp(context) => context,
|
|
||||||
ExpnDataDecodeMode::Metadata(get_context) => {
|
|
||||||
let krate = CrateNum::decode(d)?;
|
|
||||||
get_context(krate)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Do this after decoding, so that we decode a `CrateNum`
|
let expn_id = expn_id.to_expn_id();
|
||||||
// if necessary
|
|
||||||
if index == ExpnId::root().as_u32() {
|
let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id);
|
||||||
|
debug_assert!(_old_id.is_none());
|
||||||
|
expn_id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register an expansion which has been decoded from the metadata of a foreign crate.
|
||||||
|
pub fn register_expn_id(
|
||||||
|
krate: CrateNum,
|
||||||
|
local_id: ExpnIndex,
|
||||||
|
data: ExpnData,
|
||||||
|
hash: ExpnHash,
|
||||||
|
) -> ExpnId {
|
||||||
|
let expn_id = ExpnId { krate, local_id };
|
||||||
|
HygieneData::with(|hygiene_data| {
|
||||||
|
let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data);
|
||||||
|
debug_assert!(_old_data.is_none());
|
||||||
|
let _old_hash = hygiene_data.foreign_expn_hashes.insert(expn_id, hash);
|
||||||
|
debug_assert!(_old_hash.is_none());
|
||||||
|
let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id);
|
||||||
|
debug_assert!(_old_id.is_none());
|
||||||
|
});
|
||||||
|
expn_id
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decode an expansion from the metadata of a foreign crate.
|
||||||
|
pub fn decode_expn_id(
|
||||||
|
krate: CrateNum,
|
||||||
|
index: u32,
|
||||||
|
decode_data: impl FnOnce(ExpnId) -> (ExpnData, ExpnHash),
|
||||||
|
) -> ExpnId {
|
||||||
|
if index == 0 {
|
||||||
debug!("decode_expn_id: deserialized root");
|
debug!("decode_expn_id: deserialized root");
|
||||||
return Ok(ExpnId::root());
|
return ExpnId::root();
|
||||||
}
|
}
|
||||||
|
|
||||||
let outer_expns = &context.remapped_expns;
|
let index = ExpnIndex::from_u32(index);
|
||||||
|
|
||||||
// Ensure that the lock() temporary is dropped early
|
// This function is used to decode metadata, so it cannot decode information about LOCAL_CRATE.
|
||||||
{
|
debug_assert_ne!(krate, LOCAL_CRATE);
|
||||||
if let Some(expn_id) = outer_expns.lock().get(index as usize).copied().flatten() {
|
let expn_id = ExpnId { krate, local_id: index };
|
||||||
return Ok(expn_id);
|
|
||||||
}
|
// Fast path if the expansion has already been decoded.
|
||||||
|
if HygieneData::with(|hygiene_data| hygiene_data.foreign_expn_data.contains_key(&expn_id)) {
|
||||||
|
return expn_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't decode the data inside `HygieneData::with`, since we need to recursively decode
|
// Don't decode the data inside `HygieneData::with`, since we need to recursively decode
|
||||||
// other ExpnIds
|
// other ExpnIds
|
||||||
let (mut expn_data, hash) = decode_data(d, index)?;
|
let (expn_data, hash) = decode_data(expn_id);
|
||||||
|
|
||||||
let expn_id = HygieneData::with(|hygiene_data| {
|
register_expn_id(krate, index, expn_data, hash)
|
||||||
if let Some(&expn_id) = hygiene_data.expn_hash_to_expn_id.get(&hash) {
|
|
||||||
return expn_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
let expn_id = ExpnId(hygiene_data.expn_data.len() as u32);
|
|
||||||
|
|
||||||
// If we just deserialized an `ExpnData` owned by
|
|
||||||
// the local crate, its `orig_id` will be stale,
|
|
||||||
// so we need to update it to its own value.
|
|
||||||
// This only happens when we deserialize the incremental cache,
|
|
||||||
// since a crate will never decode its own metadata.
|
|
||||||
if expn_data.krate == LOCAL_CRATE {
|
|
||||||
expn_data.orig_id = Some(expn_id.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
hygiene_data.expn_data.push(Some(expn_data));
|
|
||||||
hygiene_data.expn_hashes.push(hash);
|
|
||||||
let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id);
|
|
||||||
debug_assert!(_old_id.is_none());
|
|
||||||
|
|
||||||
let mut expns = outer_expns.lock();
|
|
||||||
let new_len = index as usize + 1;
|
|
||||||
if expns.len() < new_len {
|
|
||||||
expns.resize(new_len, None);
|
|
||||||
}
|
|
||||||
expns[index as usize] = Some(expn_id);
|
|
||||||
drop(expns);
|
|
||||||
expn_id
|
|
||||||
});
|
|
||||||
Ok(expn_id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decodes `SyntaxContext`, using the provided `HygieneDecodeContext`
|
// Decodes `SyntaxContext`, using the provided `HygieneDecodeContext`
|
||||||
@ -1234,29 +1352,37 @@ fn for_all_ctxts_in<E, F: FnMut(u32, SyntaxContext, &SyntaxContextData) -> Resul
|
|||||||
|
|
||||||
fn for_all_expns_in<E>(
|
fn for_all_expns_in<E>(
|
||||||
expns: impl Iterator<Item = ExpnId>,
|
expns: impl Iterator<Item = ExpnId>,
|
||||||
mut f: impl FnMut(u32, ExpnId, ExpnData, ExpnHash) -> Result<(), E>,
|
mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash) -> Result<(), E>,
|
||||||
) -> Result<(), E> {
|
) -> Result<(), E> {
|
||||||
let all_data: Vec<_> = HygieneData::with(|data| {
|
let all_data: Vec<_> = HygieneData::with(|data| {
|
||||||
expns
|
expns
|
||||||
.map(|expn| {
|
.map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn).clone()))
|
||||||
let idx = expn.0 as usize;
|
|
||||||
(expn, data.expn_data[idx].clone(), data.expn_hashes[idx].clone())
|
|
||||||
})
|
|
||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
for (expn, data, hash) in all_data.into_iter() {
|
for (expn, data, hash) in all_data.into_iter() {
|
||||||
let data = data.unwrap_or_else(|| panic!("Missing data for {:?}", expn));
|
f(expn, &data, hash)?;
|
||||||
f(expn.0, expn, data, hash)?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E: Encoder> Encodable<E> for LocalExpnId {
|
||||||
|
fn encode(&self, e: &mut E) -> Result<(), E::Error> {
|
||||||
|
self.to_expn_id().encode(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: Encoder> Encodable<E> for ExpnId {
|
impl<E: Encoder> Encodable<E> for ExpnId {
|
||||||
default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
|
default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
|
||||||
panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::<E>());
|
panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::<E>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<D: Decoder> Decodable<D> for LocalExpnId {
|
||||||
|
fn decode(d: &mut D) -> Result<Self, D::Error> {
|
||||||
|
ExpnId::decode(d).map(ExpnId::expect_local)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<D: Decoder> Decodable<D> for ExpnId {
|
impl<D: Decoder> Decodable<D> for ExpnId {
|
||||||
default fn decode(_: &mut D) -> Result<Self, D::Error> {
|
default fn decode(_: &mut D) -> Result<Self, D::Error> {
|
||||||
panic!("cannot decode `ExpnId` with `{}`", std::any::type_name::<D>());
|
panic!("cannot decode `ExpnId` with `{}`", std::any::type_name::<D>());
|
||||||
@ -1274,58 +1400,6 @@ pub fn raw_encode_syntax_context<E: Encoder>(
|
|||||||
ctxt.0.encode(e)
|
ctxt.0.encode(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raw_encode_expn_id<E: Encoder>(
|
|
||||||
expn: ExpnId,
|
|
||||||
context: &HygieneEncodeContext,
|
|
||||||
mode: ExpnDataEncodeMode,
|
|
||||||
e: &mut E,
|
|
||||||
) -> Result<(), E::Error> {
|
|
||||||
// Record the fact that we need to serialize the corresponding
|
|
||||||
// `ExpnData`
|
|
||||||
let needs_data = || {
|
|
||||||
if !context.serialized_expns.lock().contains(&expn) {
|
|
||||||
context.latest_expns.lock().insert(expn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match mode {
|
|
||||||
ExpnDataEncodeMode::IncrComp => {
|
|
||||||
// Always serialize the `ExpnData` in incr comp mode
|
|
||||||
needs_data();
|
|
||||||
expn.0.encode(e)
|
|
||||||
}
|
|
||||||
ExpnDataEncodeMode::Metadata => {
|
|
||||||
let data = expn.expn_data();
|
|
||||||
// We only need to serialize the ExpnData
|
|
||||||
// if it comes from this crate.
|
|
||||||
// We currently don't serialize any hygiene information data for
|
|
||||||
// proc-macro crates: see the `SpecializedEncoder<Span>` impl
|
|
||||||
// for crate metadata.
|
|
||||||
if data.krate == LOCAL_CRATE {
|
|
||||||
needs_data();
|
|
||||||
}
|
|
||||||
data.orig_id.expect("Missing orig_id").encode(e)?;
|
|
||||||
data.krate.encode(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ExpnDataEncodeMode {
|
|
||||||
IncrComp,
|
|
||||||
Metadata,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ExpnDataDecodeMode<'a, F: FnOnce(CrateNum) -> &'a HygieneDecodeContext> {
|
|
||||||
IncrComp(&'a HygieneDecodeContext),
|
|
||||||
Metadata(F),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ExpnDataDecodeMode<'a, Box<dyn FnOnce(CrateNum) -> &'a HygieneDecodeContext>> {
|
|
||||||
pub fn incr_comp(ctxt: &'a HygieneDecodeContext) -> Self {
|
|
||||||
ExpnDataDecodeMode::IncrComp(ctxt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Encoder> Encodable<E> for SyntaxContext {
|
impl<E: Encoder> Encodable<E> for SyntaxContext {
|
||||||
default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
|
default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
|
||||||
panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::<E>());
|
panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::<E>());
|
||||||
@ -1345,10 +1419,9 @@ impl<D: Decoder> Decodable<D> for SyntaxContext {
|
|||||||
/// This method is called only when an `ExpnData` is first associated
|
/// This method is called only when an `ExpnData` is first associated
|
||||||
/// with an `ExpnId` (when the `ExpnId` is initially constructed, or via
|
/// with an `ExpnId` (when the `ExpnId` is initially constructed, or via
|
||||||
/// `set_expn_data`). It is *not* called for foreign `ExpnId`s deserialized
|
/// `set_expn_data`). It is *not* called for foreign `ExpnId`s deserialized
|
||||||
/// from another crate's metadata - since `ExpnData` includes a `krate` field,
|
/// from another crate's metadata - since `ExpnHash` includes the stable crate id,
|
||||||
/// collisions are only possible between `ExpnId`s within the same crate.
|
/// collisions are only possible between `ExpnId`s within the same crate.
|
||||||
fn update_disambiguator(expn_id: ExpnId, mut ctx: impl HashStableContext) {
|
fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContext) -> ExpnHash {
|
||||||
let mut expn_data = expn_id.expn_data();
|
|
||||||
// This disambiguator should not have been set yet.
|
// This disambiguator should not have been set yet.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
expn_data.disambiguator, 0,
|
expn_data.disambiguator, 0,
|
||||||
@ -1367,8 +1440,7 @@ fn update_disambiguator(expn_id: ExpnId, mut ctx: impl HashStableContext) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if disambiguator != 0 {
|
if disambiguator != 0 {
|
||||||
debug!("Set disambiguator for {:?} (hash {:?})", expn_id, expn_hash);
|
debug!("Set disambiguator for expn_data={:?} expn_hash={:?}", expn_data, expn_hash);
|
||||||
debug!("expn_data = {:?}", expn_data);
|
|
||||||
|
|
||||||
expn_data.disambiguator = disambiguator;
|
expn_data.disambiguator = disambiguator;
|
||||||
expn_hash = expn_data.hash_expn(&mut ctx);
|
expn_hash = expn_data.hash_expn(&mut ctx);
|
||||||
@ -1384,14 +1456,7 @@ fn update_disambiguator(expn_id: ExpnId, mut ctx: impl HashStableContext) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let expn_hash = ExpnHash(expn_hash);
|
ExpnHash::new(ctx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), expn_hash)
|
||||||
HygieneData::with(|data| {
|
|
||||||
data.expn_data[expn_id.0 as usize].as_mut().unwrap().disambiguator = disambiguator;
|
|
||||||
debug_assert_eq!(data.expn_hashes[expn_id.0 as usize].0, Fingerprint::ZERO);
|
|
||||||
data.expn_hashes[expn_id.0 as usize] = expn_hash;
|
|
||||||
let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, expn_id);
|
|
||||||
debug_assert!(_old_id.is_none());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<CTX: HashStableContext> HashStable<CTX> for SyntaxContext {
|
impl<CTX: HashStableContext> HashStable<CTX> for SyntaxContext {
|
||||||
|
@ -38,7 +38,7 @@ use edition::Edition;
|
|||||||
pub mod hygiene;
|
pub mod hygiene;
|
||||||
use hygiene::Transparency;
|
use hygiene::Transparency;
|
||||||
pub use hygiene::{DesugaringKind, ExpnKind, ForLoopLoc, MacroKind};
|
pub use hygiene::{DesugaringKind, ExpnKind, ForLoopLoc, MacroKind};
|
||||||
pub use hygiene::{ExpnData, ExpnHash, ExpnId, SyntaxContext};
|
pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
|
||||||
pub mod def_id;
|
pub mod def_id;
|
||||||
use def_id::{CrateNum, DefId, DefPathHash, LOCAL_CRATE};
|
use def_id::{CrateNum, DefId, DefPathHash, LOCAL_CRATE};
|
||||||
pub mod lev_distance;
|
pub mod lev_distance;
|
||||||
|
@ -19,10 +19,10 @@ fn y /* 0#0 */() { }
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Expansions:
|
Expansions:
|
||||||
0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
|
crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
|
||||||
1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "foo")
|
crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "foo")
|
||||||
|
|
||||||
SyntaxContexts:
|
SyntaxContexts:
|
||||||
#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
|
#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
|
||||||
#1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent)
|
#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiTransparent)
|
||||||
*/
|
*/
|
||||||
|
@ -43,23 +43,23 @@ fn main /* 0#0 */() { ; }
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Expansions:
|
Expansions:
|
||||||
0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
|
crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
|
||||||
1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
|
crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
|
||||||
2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it")
|
crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it")
|
||||||
3: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
|
crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
|
||||||
4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
|
crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy")
|
||||||
5: parent: ExpnId(4), call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy")
|
crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
|
||||||
|
|
||||||
SyntaxContexts:
|
SyntaxContexts:
|
||||||
#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
|
#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
|
||||||
#1: parent: #0, outer_mark: (ExpnId(1), Opaque)
|
#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
|
||||||
#2: parent: #0, outer_mark: (ExpnId(1), Transparent)
|
#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
|
||||||
#3: parent: #0, outer_mark: (ExpnId(3), Opaque)
|
#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque)
|
||||||
#4: parent: #0, outer_mark: (ExpnId(2), SemiTransparent)
|
#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
|
||||||
#5: parent: #0, outer_mark: (ExpnId(4), Opaque)
|
#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
|
||||||
#6: parent: #4, outer_mark: (ExpnId(4), Transparent)
|
#6: parent: #4, outer_mark: (crate0::{{expn3}}, Transparent)
|
||||||
#7: parent: #0, outer_mark: (ExpnId(4), SemiTransparent)
|
#7: parent: #0, outer_mark: (crate0::{{expn3}}, SemiTransparent)
|
||||||
#8: parent: #0, outer_mark: (ExpnId(5), Opaque)
|
#8: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
|
||||||
#9: parent: #5, outer_mark: (ExpnId(5), Transparent)
|
#9: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent)
|
||||||
#10: parent: #5, outer_mark: (ExpnId(5), SemiTransparent)
|
#10: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
|
||||||
*/
|
*/
|
||||||
|
@ -67,22 +67,22 @@ fn main /* 0#0 */() { }
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Expansions:
|
Expansions:
|
||||||
0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
|
crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
|
||||||
1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
|
crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
|
||||||
2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
|
crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
|
||||||
3: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
|
crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner")
|
||||||
4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner")
|
crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
|
||||||
5: parent: ExpnId(4), call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
|
crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
|
||||||
|
|
||||||
SyntaxContexts:
|
SyntaxContexts:
|
||||||
#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
|
#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
|
||||||
#1: parent: #0, outer_mark: (ExpnId(1), Opaque)
|
#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
|
||||||
#2: parent: #0, outer_mark: (ExpnId(1), Transparent)
|
#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
|
||||||
#3: parent: #0, outer_mark: (ExpnId(3), Opaque)
|
#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque)
|
||||||
#4: parent: #0, outer_mark: (ExpnId(2), SemiTransparent)
|
#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
|
||||||
#5: parent: #0, outer_mark: (ExpnId(4), Opaque)
|
#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
|
||||||
#6: parent: #4, outer_mark: (ExpnId(4), Opaque)
|
#6: parent: #4, outer_mark: (crate0::{{expn3}}, Opaque)
|
||||||
#7: parent: #0, outer_mark: (ExpnId(5), Opaque)
|
#7: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
|
||||||
#8: parent: #6, outer_mark: (ExpnId(5), Transparent)
|
#8: parent: #6, outer_mark: (crate0::{{expn4}}, Transparent)
|
||||||
#9: parent: #5, outer_mark: (ExpnId(5), SemiTransparent)
|
#9: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
|
||||||
*/
|
*/
|
||||||
|
@ -6,7 +6,7 @@ use rustc_ast::ast::{
|
|||||||
};
|
};
|
||||||
use rustc_ast::ptr;
|
use rustc_ast::ptr;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_span::{sym, symbol, BytePos, ExpnId, Span, Symbol, SyntaxContext};
|
use rustc_span::{sym, symbol, BytePos, LocalExpnId, Span, Symbol, SyntaxContext};
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses};
|
use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses};
|
||||||
@ -675,7 +675,7 @@ pub(crate) trait NodeIdExt {
|
|||||||
|
|
||||||
impl NodeIdExt for NodeId {
|
impl NodeIdExt for NodeId {
|
||||||
fn root() -> NodeId {
|
fn root() -> NodeId {
|
||||||
NodeId::placeholder_from_expn_id(ExpnId::root())
|
NodeId::placeholder_from_expn_id(LocalExpnId::ROOT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user