Skip to content

Commit

Permalink
Make use of hygiene in AST passes
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewjasper committed Sep 5, 2019
1 parent 4082cd9 commit 6fcdb36
Show file tree
Hide file tree
Showing 15 changed files with 298 additions and 257 deletions.
27 changes: 16 additions & 11 deletions src/librustc_interface/passes.rs
Expand Up @@ -233,7 +233,7 @@ pub fn register_plugins<'a>(
syntax::attr::inject(krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr)
});

let (mut krate, features) = syntax::config::features(
let (krate, features) = syntax::config::features(
krate,
&sess.parse_sess,
sess.edition(),
Expand Down Expand Up @@ -268,16 +268,6 @@ pub fn register_plugins<'a>(
middle::recursion_limit::update_limits(sess, &krate);
});

krate = time(sess, "crate injection", || {
let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s);
let (krate, name) =
syntax_ext::standard_library_imports::inject(krate, alt_std_name, sess.edition());
if let Some(name) = name {
sess.parse_sess.injected_crate_name.set(name);
}
krate
});

let registrars = time(sess, "plugin loading", || {
plugin::load::load_plugins(
sess,
Expand Down Expand Up @@ -370,6 +360,21 @@ fn configure_and_expand_inner<'a>(
&resolver_arenas,
);
syntax_ext::register_builtin_macros(&mut resolver, sess.edition());

krate = time(sess, "crate injection", || {
let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s));
let (krate, name) = syntax_ext::standard_library_imports::inject(
krate,
&mut resolver,
alt_std_name,
sess.edition(),
);
if let Some(name) = name {
sess.parse_sess.injected_crate_name.set(name);
}
krate
});

syntax_ext::plugin_macro_defs::inject(
&mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition()
);
Expand Down
10 changes: 0 additions & 10 deletions src/librustc_resolve/macros.rs
Expand Up @@ -97,16 +97,6 @@ impl<'a> base::Resolver for Resolver<'a> {
self.session.next_node_id()
}

fn get_module_scope(&mut self, id: NodeId) -> ExpnId {
let expn_id = ExpnId::fresh(Some(ExpnData::default(
ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, self.session.edition()
)));
let module = self.module_map[&self.definitions.local_def_id(id)];
self.invocation_parent_scopes.insert(expn_id, ParentScope::module(module));
self.definitions.set_invocation_parent(expn_id, module.def_id().unwrap().index);
expn_id
}

fn resolve_dollar_crates(&mut self) {
hygiene::update_dollar_crate_names(|ctxt| {
let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
Expand Down
2 changes: 0 additions & 2 deletions src/libsyntax/ext/base.rs
Expand Up @@ -653,8 +653,6 @@ bitflags::bitflags! {
pub trait Resolver {
fn next_node_id(&mut self) -> NodeId;

fn get_module_scope(&mut self, id: NodeId) -> ExpnId;

fn resolve_dollar_crates(&mut self);
fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment,
extra_placeholders: &[NodeId]);
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax_ext/plugin_macro_defs.rs
Expand Up @@ -11,7 +11,7 @@ use syntax::source_map::respan;
use syntax::symbol::sym;
use syntax::tokenstream::*;
use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::hygiene::{ExpnData, ExpnKind, MacroKind};
use syntax_pos::hygiene::{ExpnData, ExpnKind, AstPass};

use std::mem;

Expand Down Expand Up @@ -44,7 +44,7 @@ pub fn inject(
if !named_exts.is_empty() {
let mut extra_items = Vec::new();
let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
ExpnKind::Macro(MacroKind::Attr, sym::plugin), DUMMY_SP, edition,
ExpnKind::AstPass(AstPass::PluginMacroDefs), DUMMY_SP, edition,
[sym::rustc_attrs][..].into(),
));
for (name, ext) in named_exts {
Expand Down
86 changes: 52 additions & 34 deletions src/libsyntax_ext/proc_macro_harness.rs
Expand Up @@ -3,15 +3,15 @@ use std::mem;
use smallvec::smallvec;
use syntax::ast::{self, Ident};
use syntax::attr;
use syntax::source_map::{ExpnData, ExpnKind, respan};
use syntax::ext::base::{ExtCtxt, MacroKind};
use syntax::ext::base::ExtCtxt;
use syntax::ext::expand::{AstFragment, ExpansionConfig};
use syntax::ext::proc_macro::is_proc_macro_attr;
use syntax::parse::ParseSess;
use syntax::ptr::P;
use syntax::symbol::{kw, sym};
use syntax::visit::{self, Visitor};
use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::hygiene::AstPass;

struct ProcMacroDerive {
trait_name: ast::Name,
Expand Down Expand Up @@ -308,8 +308,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {

// Creates a new module which looks like:
//
// #[doc(hidden)]
// mod $gensym {
// const _: () = {
// extern crate proc_macro;
//
// use proc_macro::bridge::client::ProcMacro;
Expand All @@ -327,32 +326,29 @@ fn mk_decls(
custom_attrs: &[ProcMacroDef],
custom_macros: &[ProcMacroDef],
) -> P<ast::Item> {
let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
ExpnKind::Macro(MacroKind::Attr, sym::proc_macro), DUMMY_SP, cx.parse_sess.edition,
[sym::rustc_attrs, sym::proc_macro_internals][..].into(),
));

let hidden = cx.meta_list_item_word(span, sym::hidden);
let doc = cx.meta_list(span, sym::doc, vec![hidden]);
let doc_hidden = cx.attribute(doc);

let proc_macro = Ident::with_dummy_span(sym::proc_macro);
let span = cx.resolver.span_for_ast_pass(
DUMMY_SP,
AstPass::ProcMacroHarness,
&[sym::rustc_attrs, sym::proc_macro_internals],
None,
);

let proc_macro = Ident::new(sym::proc_macro, span);
let krate = cx.item(span,
proc_macro,
Vec::new(),
ast::ItemKind::ExternCrate(None));

let bridge = Ident::from_str("bridge");
let client = Ident::from_str("client");
let proc_macro_ty = Ident::from_str("ProcMacro");
let custom_derive = Ident::from_str("custom_derive");
let attr = Ident::from_str("attr");
let bang = Ident::from_str("bang");
let crate_kw = Ident::with_dummy_span(kw::Crate);
let bridge = Ident::from_str_and_span("bridge", span);
let client = Ident::from_str_and_span("client", span);
let proc_macro_ty = Ident::from_str_and_span("ProcMacro", span);
let custom_derive = Ident::from_str_and_span("custom_derive", span);
let attr = Ident::from_str_and_span("attr", span);
let bang = Ident::from_str_and_span("bang", span);

let decls = {
let local_path = |sp: Span, name| {
cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![crate_kw, name]))
cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![name]))
};
let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![
proc_macro, bridge, client, proc_macro_ty, method,
Expand Down Expand Up @@ -381,7 +377,7 @@ fn mk_decls(

let decls_static = cx.item_static(
span,
Ident::from_str("_DECLS"),
Ident::from_str_and_span("_DECLS", span),
cx.ty_rptr(span,
cx.ty(span, ast::TyKind::Slice(
cx.ty_path(cx.path(span,
Expand All @@ -392,22 +388,44 @@ fn mk_decls(
).map(|mut i| {
let attr = cx.meta_word(span, sym::rustc_proc_macro_decls);
i.attrs.push(cx.attribute(attr));
i.vis = respan(span, ast::VisibilityKind::Public);
i
});

let module = cx.item_mod(
span,
let block = P(ast::Expr {
id: ast::DUMMY_NODE_ID,
attrs: syntax::ThinVec::new(),
node: ast::ExprKind::Block(P(ast::Block {
id: ast::DUMMY_NODE_ID,
rules: ast::BlockCheckMode::Default,
stmts: vec![
ast::Stmt {
id: ast::DUMMY_NODE_ID,
node: ast::StmtKind::Item(krate),
span,
},
ast::Stmt {
id: ast::DUMMY_NODE_ID,
node: ast::StmtKind::Item(decls_static),
span,
}
],
span,
}), None),
span,
ast::Ident::from_str("decls").gensym(),
vec![doc_hidden],
vec![krate, decls_static],
).map(|mut i| {
i.vis = respan(span, ast::VisibilityKind::Public);
i
});

let anon_constant = cx.item_const(
span,
ast::Ident::new(kw::Underscore, span),
P(ast::Ty {
id: ast::DUMMY_NODE_ID,
node: ast::TyKind::Tup(Vec::new()),
span,
}),
block,
);

// Integrate the new module into existing module structures.
let module = AstFragment::Items(smallvec![module]);
cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap()
let items = AstFragment::Items(smallvec![anon_constant]);
cx.monotonic_expander().fully_expand_fragment(items).make_items().pop().unwrap()
}

0 comments on commit 6fcdb36

Please sign in to comment.