Allow ast passes to create hygienic spans

This commit is contained in:
Matthew Jasper 2019-08-25 20:58:03 +01:00
parent 0133941f47
commit 4082cd95a8
5 changed files with 72 additions and 4 deletions

View File

@ -126,7 +126,8 @@ impl<'a> Resolver<'a> {
crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
let def_id = match self.macro_defs.get(&expn_id) {
Some(def_id) => *def_id,
None => return self.graph_root,
None => return self.ast_transform_scopes.get(&expn_id)
.unwrap_or(&self.graph_root),
};
if let Some(id) = self.definitions.as_local_node_id(def_id) {
self.local_macro_def_scopes[&id]

View File

@ -879,6 +879,10 @@ pub struct Resolver<'a> {
/// There will be an anonymous module created around `g` with the ID of the
/// entry block for `f`.
block_map: NodeMap<Module<'a>>,
/// A fake module that contains no definition and no prelude. Used so that
/// some AST passes can generate identifiers that only resolve to local or
/// language items.
empty_module: Module<'a>,
module_map: FxHashMap<DefId, Module<'a>>,
extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>,
binding_parent_modules: FxHashMap<PtrKey<'a, NameBinding<'a>>, Module<'a>>,
@ -913,6 +917,7 @@ pub struct Resolver<'a> {
non_macro_attrs: [Lrc<SyntaxExtension>; 2],
macro_defs: FxHashMap<ExpnId, DefId>,
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
ast_transform_scopes: FxHashMap<ExpnId, Module<'a>>,
unused_macros: NodeMap<Span>,
proc_macro_stubs: NodeSet,
/// Traces collected during macro resolution and validated when it's complete.
@ -1080,6 +1085,21 @@ impl<'a> Resolver<'a> {
no_implicit_prelude: attr::contains_name(&krate.attrs, sym::no_implicit_prelude),
..ModuleData::new(None, root_module_kind, root_def_id, ExpnId::root(), krate.span)
});
let empty_module_kind = ModuleKind::Def(
DefKind::Mod,
root_def_id,
kw::Invalid,
);
let empty_module = arenas.alloc_module(ModuleData {
no_implicit_prelude: true,
..ModuleData::new(
Some(graph_root),
empty_module_kind,
root_def_id,
ExpnId::root(),
DUMMY_SP,
)
});
let mut module_map = FxHashMap::default();
module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
@ -1139,10 +1159,12 @@ impl<'a> Resolver<'a> {
label_res_map: Default::default(),
export_map: FxHashMap::default(),
trait_map: Default::default(),
empty_module,
module_map,
block_map: Default::default(),
extern_module_map: FxHashMap::default(),
binding_parent_modules: FxHashMap::default(),
ast_transform_scopes: FxHashMap::default(),
glob_map: Default::default(),

View File

@ -8,6 +8,7 @@ use crate::{ModuleOrUniformRoot, KNOWN_TOOLS};
use crate::Namespace::*;
use crate::resolve_imports::ImportResolver;
use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
use rustc::hir::def_id;
use rustc::middle::stability;
use rustc::{ty, lint, span_bug};
use syntax::ast::{self, NodeId, Ident};
@ -16,7 +17,7 @@ use syntax::edition::Edition;
use syntax::ext::base::{self, Indeterminate, SpecialDerives};
use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind};
use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind, Transparency};
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name};
use syntax::feature_gate::GateIssue;
@ -25,6 +26,7 @@ use syntax_pos::{Span, DUMMY_SP};
use std::{mem, ptr};
use rustc_data_structures::sync::Lrc;
use syntax_pos::hygiene::AstPass;
type Res = def::Res<NodeId>;
@ -136,6 +138,41 @@ impl<'a> base::Resolver for Resolver<'a> {
}
}
// Create a Span with modern hygiene with a definition site of the provided
// module, or a fake empty `#[no_implicit_prelude]` module if no module is
// provided.
fn span_for_ast_pass(
&mut self,
base_span: Span,
pass: AstPass,
features: &[Symbol],
parent_module_id: Option<NodeId>,
) -> Span {
let span = base_span.fresh_expansion_with_transparency(
ExpnData::allow_unstable(
ExpnKind::AstPass(pass),
base_span,
self.session.edition(),
features.into(),
),
Transparency::Opaque,
);
let expn_id = span.ctxt().outer_expn();
let parent_scope = if let Some(module_id) = parent_module_id {
let parent_def_id = self.definitions.local_def_id(module_id);
self.definitions.add_parent_module_of_macro_def(expn_id, parent_def_id);
self.module_map[&parent_def_id]
} else {
self.definitions.add_parent_module_of_macro_def(
expn_id,
def_id::DefId::local(def_id::CRATE_DEF_INDEX),
);
self.empty_module
};
self.ast_transform_scopes.insert(expn_id, parent_scope);
span
}
fn resolve_imports(&mut self) {
ImportResolver { r: self }.resolve_imports()
}

View File

@ -15,7 +15,7 @@ use crate::tokenstream::{self, TokenStream, TokenTree};
use errors::{DiagnosticBuilder, DiagnosticId};
use smallvec::{smallvec, SmallVec};
use syntax_pos::{FileName, Span, MultiSpan, DUMMY_SP};
use syntax_pos::hygiene::{ExpnData, ExpnKind};
use syntax_pos::hygiene::{AstPass, ExpnData, ExpnKind};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::{self, Lrc};
@ -660,6 +660,14 @@ pub trait Resolver {
extra_placeholders: &[NodeId]);
fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension);
fn span_for_ast_pass(
&mut self,
span: Span,
pass: AstPass,
features: &[Symbol],
parent_module_id: Option<NodeId>,
) -> Span;
fn resolve_imports(&mut self);
fn resolve_macro_invocation(

View File

@ -550,7 +550,7 @@ impl Span {
/// The returned span belongs to the created expansion and has the new properties,
/// but its location is inherited from the current span.
pub fn fresh_expansion(self, expn_data: ExpnData) -> Span {
self.fresh_expansion_with_transparency(expn_data, Transparency::SemiTransparent)
self.fresh_expansion_with_transparency(expn_data, Transparency::Transparent)
}
pub fn fresh_expansion_with_transparency(