From 9c7969d3df6ce1cd5370eea32f18a08dc1f0850d Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 6 Dec 2017 10:50:55 -0800 Subject: Use hygiene to access the injected crate (`core` or `std`) from builtin macros. --- src/libsyntax/ext/base.rs | 15 ++++++--------- src/libsyntax/ext/build.rs | 5 ++++- src/libsyntax/ext/expand.rs | 2 -- src/libsyntax/test.rs | 3 +-- 4 files changed, 11 insertions(+), 14 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 6c96692f719..bb1b7da7dba 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -21,10 +21,11 @@ use fold::{self, Folder}; use parse::{self, parser, DirectoryOwnership}; use parse::token; use ptr::P; -use symbol::Symbol; +use symbol::{keywords, Ident, Symbol}; use util::small_vector::SmallVector; use std::collections::HashMap; +use std::iter; use std::path::PathBuf; use std::rc::Rc; use std::default::Default; @@ -664,7 +665,6 @@ pub struct ExpansionData { pub struct ExtCtxt<'a> { pub parse_sess: &'a parse::ParseSess, pub ecfg: expand::ExpansionConfig<'a>, - pub crate_root: Option<&'static str>, pub root_path: PathBuf, pub resolver: &'a mut Resolver, pub resolve_err_count: usize, @@ -680,7 +680,6 @@ impl<'a> ExtCtxt<'a> { ExtCtxt { parse_sess, ecfg, - crate_root: None, root_path: PathBuf::new(), resolver, resolve_err_count: 0, @@ -822,12 +821,10 @@ impl<'a> ExtCtxt<'a> { ast::Ident::from_str(st) } pub fn std_path(&self, components: &[&str]) -> Vec { - let mut v = Vec::new(); - if let Some(s) = self.crate_root { - v.push(self.ident_of(s)); - } - v.extend(components.iter().map(|s| self.ident_of(s))); - v + let def_site = SyntaxContext::empty().apply_mark(self.current_expansion.mark); + iter::once(Ident { ctxt: def_site, ..keywords::DollarCrate.ident() }) + .chain(components.iter().map(|s| self.ident_of(s))) + .collect() } pub fn name_of(&self, st: &str) -> ast::Name { Symbol::intern(st) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 25eef6db930..82e7747b014 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -319,9 +319,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> { types: Vec>, bindings: Vec ) -> ast::Path { + use syntax::parse::token; + let last_identifier = idents.pop().unwrap(); let mut segments: Vec = Vec::new(); - if global { + if global && + !idents.first().map_or(false, |&ident| token::Ident(ident).is_path_segment_keyword()) { segments.push(ast::PathSegment::crate_root(span)); } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 0d1b1c65a29..ecb396f259f 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -25,7 +25,6 @@ use parse::{DirectoryOwnership, PResult}; use parse::token::{self, Token}; use parse::parser::Parser; use ptr::P; -use std_inject; use symbol::Symbol; use symbol::keywords; use syntax_pos::{Span, DUMMY_SP}; @@ -219,7 +218,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { - self.cx.crate_root = std_inject::injected_crate_name(&krate); let mut module = ModuleData { mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)], directory: self.cx.codemap().span_to_unmapped_path(krate.span), diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index a4ac5826f99..9f097169d97 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -272,7 +272,7 @@ fn generate_test_harness(sess: &ParseSess, let mark = Mark::fresh(Mark::root()); - let mut cx: TestCtxt = TestCtxt { + let cx = TestCtxt { span_diagnostic: sd, ext_cx: ExtCtxt::new(sess, ExpansionConfig::default("test".to_string()), resolver), path: Vec::new(), @@ -283,7 +283,6 @@ fn generate_test_harness(sess: &ParseSess, toplevel_reexport: None, ctxt: SyntaxContext::empty().apply_mark(mark), }; - cx.ext_cx.crate_root = Some("std"); mark.set_expn_info(ExpnInfo { call_site: DUMMY_SP, -- cgit 1.4.1-3-g733a5 From 85d19b33357897c51d80727a4208f46b19c5c5a6 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 12 Dec 2017 11:57:58 -0800 Subject: Improve pretty printing `$crate::` paths. --- src/librustc/hir/lowering.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 3 ++- src/librustc_resolve/lib.rs | 3 --- src/librustc_resolve/macros.rs | 11 +++++++---- src/libsyntax/print/pprust.rs | 20 +++++++++++++++++++- src/libsyntax/std_inject.rs | 26 +++++++++++++++----------- 6 files changed, 44 insertions(+), 21 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 63b80a3f3c1..ce118240429 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -175,7 +175,7 @@ pub fn lower_crate(sess: &Session, let _ignore = dep_graph.in_ignore(); LoweringContext { - crate_root: std_inject::injected_crate_name(krate), + crate_root: std_inject::injected_crate_name(), sess, cstore, parent_def: None, diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index cc5ed59ac6a..6ec7f07456a 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -40,6 +40,7 @@ use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; use syntax::parse::token::{self, Token}; +use syntax::std_inject::injected_crate_name; use syntax::symbol::keywords; use syntax::symbol::Symbol; use syntax::visit::{self, Visitor}; @@ -262,7 +263,7 @@ impl<'a> Resolver<'a> { let module = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); self.populate_module_if_necessary(module); - if self.injected_crate_name.map_or(false, |name| item.ident.name == name) { + if injected_crate_name().map_or(false, |name| item.ident.name == name) { self.injected_crate = Some(module); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6de61df16b2..b114c5734a5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -58,7 +58,6 @@ use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; use syntax::ast::{Local, Mutability, Pat, PatKind, Path}; use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; use syntax::feature_gate::{feature_err, emit_feature_err, GateIssue}; -use syntax::std_inject::injected_crate_name; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use errors::{DiagnosticBuilder, DiagnosticId}; @@ -1335,7 +1334,6 @@ pub struct Resolver<'a> { // Only used for better errors on `fn(): fn()` current_type_ascription: Vec, - injected_crate_name: Option<&'static str>, injected_crate: Option>, } @@ -1536,7 +1534,6 @@ impl<'a> Resolver<'a> { found_unresolved_macro: false, unused_macros: FxHashSet(), current_type_ascription: Vec::new(), - injected_crate_name: injected_crate_name(krate), injected_crate: None, } } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 3d1d7c0c48a..f6b2a8dd861 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -25,7 +25,7 @@ use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator}; use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver}; use syntax::ext::expand::{Expansion, ExpansionKind, Invocation, InvocationKind, find_attr_invoc}; -use syntax::ext::hygiene::Mark; +use syntax::ext::hygiene::{Mark, MarkKind}; use syntax::ext::placeholders::placeholder; use syntax::ext::tt::macro_rules; use syntax::feature_gate::{self, emit_feature_err, GateIssue}; @@ -297,16 +297,19 @@ impl<'a> base::Resolver for Resolver<'a> { InvocationKind::Attr { attr: None, .. } => return Ok(None), _ => self.resolve_invoc_to_def(invoc, scope, force)?, }; + let def_id = def.def_id(); - self.macro_defs.insert(invoc.expansion_data.mark, def.def_id()); + self.macro_defs.insert(invoc.expansion_data.mark, def_id); let normal_module_def_id = self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id; self.definitions.add_macro_def_scope(invoc.expansion_data.mark, normal_module_def_id); - self.unused_macros.remove(&def.def_id()); + self.unused_macros.remove(&def_id); let ext = self.get_macro(def); if ext.is_modern() { - invoc.expansion_data.mark.set_modern(); + invoc.expansion_data.mark.set_kind(MarkKind::Modern); + } else if def_id.krate == BUILTIN_MACROS_CRATE { + invoc.expansion_data.mark.set_kind(MarkKind::Builtin); } Ok(Some(ext)) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a2d3ed4deb6..17f37d0f2c0 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -18,6 +18,7 @@ use util::parser::{self, AssocOp, Fixity}; use attr; use codemap::{self, CodeMap}; use syntax_pos::{self, BytePos}; +use syntax_pos::hygiene::{Mark, MarkKind, SyntaxContext}; use parse::token::{self, BinOpToken, Token}; use parse::lexer::comments; use parse::{self, ParseSess}; @@ -93,7 +94,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, is_expanded: bool) -> io::Result<()> { let mut s = State::new_from_input(cm, sess, filename, input, out, ann, is_expanded); - if is_expanded && !std_inject::injected_crate_name(krate).is_none() { + if is_expanded && !std_inject::injected_crate_name().is_none() { // We need to print `#![no_std]` (and its feature gate) so that // compiling pretty-printed source won't inject libstd again. // However we don't want these attributes in the AST because @@ -734,6 +735,8 @@ pub trait PrintState<'a> { if segment.identifier.name != keywords::CrateRoot.name() && segment.identifier.name != keywords::DollarCrate.name() { self.writer().word(&segment.identifier.name.as_str())?; + } else if segment.identifier.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.identifier.ctxt)?; } } self.writer().space()?; @@ -822,6 +825,19 @@ pub trait PrintState<'a> { } fn nbsp(&mut self) -> io::Result<()> { self.writer().word(" ") } + + fn print_dollar_crate(&mut self, mut ctxt: SyntaxContext) -> io::Result<()> { + if let Some(mark) = ctxt.adjust(Mark::root()) { + // Make a best effort to print something that complies + if mark.kind() == MarkKind::Builtin { + if let Some(name) = std_inject::injected_crate_name() { + self.writer().word("::")?; + self.writer().word(name)?; + } + } + } + Ok(()) + } } impl<'a> PrintState<'a> for State<'a> { @@ -2411,6 +2427,8 @@ impl<'a> State<'a> { if let Some(ref parameters) = segment.parameters { self.print_path_parameters(parameters, colons_before_params)?; } + } else if segment.identifier.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.identifier.ctxt)?; } Ok(()) } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index ae22230198f..00546400bb5 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -10,6 +10,7 @@ use ast; use attr; +use std::cell::Cell; use ext::hygiene::{Mark, SyntaxContext}; use symbol::{Symbol, keywords}; use syntax_pos::{DUMMY_SP, Span}; @@ -34,22 +35,25 @@ fn ignored_span(sp: Span) -> Span { sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)) } -pub fn injected_crate_name(krate: &ast::Crate) -> Option<&'static str> { - if attr::contains_name(&krate.attrs, "no_core") { - None - } else if attr::contains_name(&krate.attrs, "no_std") { - Some("core") - } else { - Some("std") - } +pub fn injected_crate_name() -> Option<&'static str> { + INJECTED_CRATE_NAME.with(|name| name.get()) +} + +thread_local! { + static INJECTED_CRATE_NAME: Cell> = Cell::new(None); } pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option) -> ast::Crate { - let name = match injected_crate_name(&krate) { - Some(name) => name, - None => return krate, + let name = if attr::contains_name(&krate.attrs, "no_core") { + return krate; + } else if attr::contains_name(&krate.attrs, "no_std") { + "core" + } else { + "std" }; + INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name))); + let crate_name = Symbol::intern(&alt_std_name.unwrap_or_else(|| name.to_string())); krate.module.items.insert(0, P(ast::Item { -- cgit 1.4.1-3-g733a5