about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-12-13 11:09:55 +0000
committerbors <bors@rust-lang.org>2017-12-13 11:09:55 +0000
commit3dfbc88a626625be01e112da11ec367e2fc71bb3 (patch)
tree3123349d2f450ac5317944d5f5803b20c3eca65b /src/libsyntax
parent61100840e5c978a99b0489e8eaa922da06c05f65 (diff)
parent85d19b33357897c51d80727a4208f46b19c5c5a6 (diff)
downloadrust-3dfbc88a626625be01e112da11ec367e2fc71bb3.tar.gz
rust-3dfbc88a626625be01e112da11ec367e2fc71bb3.zip
Auto merge of #46550 - jseyfried:cleanup_builtin_hygiene, r=nrc
macros: hygienize use of `core`/`std` in builtin macros

Today, if a builtin macro wants to access an item from `core` or `std` (depending `#![no_std]`), it generates `::core::path::to::item` or `::std::path::to::item` respectively (c.f. `fn std_path()` in `libsyntax/ext/base.rs`).

This PR refactors the builtin macros to instead always emit `$crate::path::to::item` here. That is, the def site of builtin macros is taken to be in `extern crate core;` or `extern crate std;`. Since builtin macros are macros 1.0 (i.e. mostly unhygienic), changing the def site can only effect the resolution of `$crate`.

r? @nrc
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/base.rs15
-rw-r--r--src/libsyntax/ext/build.rs5
-rw-r--r--src/libsyntax/ext/expand.rs2
-rw-r--r--src/libsyntax/print/pprust.rs20
-rw-r--r--src/libsyntax/std_inject.rs26
-rw-r--r--src/libsyntax/test.rs3
6 files changed, 45 insertions, 26 deletions
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<ast::Ident> {
-        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<P<ast::Ty>>,
                 bindings: Vec<ast::TypeBinding> )
                 -> ast::Path {
+        use syntax::parse::token;
+
         let last_identifier = idents.pop().unwrap();
         let mut segments: Vec<ast::PathSegment> = 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/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<Option<&'static str>> = Cell::new(None);
 }
 
 pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<String>) -> 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 {
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,