about summary refs log tree commit diff
path: root/src/libsyntax_ext/standard_library_imports.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax_ext/standard_library_imports.rs')
-rw-r--r--src/libsyntax_ext/standard_library_imports.rs130
1 files changed, 95 insertions, 35 deletions
diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs
index 8ca376341fc..61e423266fa 100644
--- a/src/libsyntax_ext/standard_library_imports.rs
+++ b/src/libsyntax_ext/standard_library_imports.rs
@@ -1,52 +1,56 @@
 use syntax::{ast, attr};
 use syntax::edition::Edition;
-use syntax::ext::hygiene::MacroKind;
+use syntax::ext::hygiene::AstPass;
+use syntax::ext::base::Resolver;
 use syntax::ptr::P;
-use syntax::source_map::{ExpnData, ExpnKind, dummy_spanned, respan};
+use syntax::source_map::respan;
 use syntax::symbol::{Ident, Symbol, kw, sym};
 use syntax_pos::DUMMY_SP;
 
-use std::iter;
-
 pub fn inject(
-    mut krate: ast::Crate, alt_std_name: Option<&str>, edition: Edition
+    mut krate: ast::Crate,
+    resolver: &mut dyn Resolver,
+    alt_std_name: Option<Symbol>,
+    edition: Edition,
 ) -> (ast::Crate, Option<Symbol>) {
     let rust_2018 = edition >= Edition::Edition2018;
 
     // the first name in this list is the crate name of the crate with the prelude
-    let names: &[&str] = if attr::contains_name(&krate.attrs, sym::no_core) {
+    let names: &[Symbol] = if attr::contains_name(&krate.attrs, sym::no_core) {
         return (krate, None);
     } else if attr::contains_name(&krate.attrs, sym::no_std) {
         if attr::contains_name(&krate.attrs, sym::compiler_builtins) {
-            &["core"]
+            &[sym::core]
         } else {
-            &["core", "compiler_builtins"]
+            &[sym::core, sym::compiler_builtins]
         }
     } else {
-        &["std"]
+        &[sym::std]
     };
 
+    let span = resolver.span_for_ast_pass(
+        DUMMY_SP,
+        AstPass::StdImports,
+        &[sym::prelude_import],
+        None,
+    );
+
     // .rev() to preserve ordering above in combination with insert(0, ...)
-    let alt_std_name = alt_std_name.map(Symbol::intern);
-    for orig_name_str in names.iter().rev() {
-        // HACK(eddyb) gensym the injected crates on the Rust 2018 edition,
-        // so they don't accidentally interfere with the new import paths.
-        let orig_name_sym = Symbol::intern(orig_name_str);
-        let orig_name_ident = Ident::with_dummy_span(orig_name_sym);
+    for &orig_name_sym in names.iter().rev() {
         let (rename, orig_name) = if rust_2018 {
-            (orig_name_ident.gensym(), Some(orig_name_sym))
+            (Ident::new(kw::Underscore, span), Some(orig_name_sym))
         } else {
-            (orig_name_ident, None)
+            (Ident::with_dummy_span(orig_name_sym), None)
         };
         krate.module.items.insert(0, P(ast::Item {
             attrs: vec![attr::mk_attr_outer(
-                attr::mk_word_item(ast::Ident::with_dummy_span(sym::macro_use))
+                attr::mk_word_item(ast::Ident::new(sym::macro_use, span))
             )],
-            vis: dummy_spanned(ast::VisibilityKind::Inherited),
+            vis: respan(span, ast::VisibilityKind::Inherited),
             node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)),
             ident: rename,
             id: ast::DUMMY_NODE_ID,
-            span: DUMMY_SP,
+            span,
             tokens: None,
         }));
     }
@@ -55,24 +59,22 @@ pub fn inject(
     // the prelude.
     let name = names[0];
 
-    let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
-        ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition,
-        [sym::prelude_import][..].into(),
-    ));
+    let segments = if rust_2018 {
+        [name, sym::prelude, sym::v1].iter()
+            .map(|symbol| ast::PathSegment::from_ident(ast::Ident::new(*symbol, span)))
+            .collect()
+    } else {
+        [kw::PathRoot, name, sym::prelude, sym::v1].iter()
+            .map(|symbol| ast::PathSegment::from_ident(ast::Ident::with_dummy_span(*symbol)))
+            .collect()
+    };
 
-    krate.module.items.insert(0, P(ast::Item {
+    let use_item = P(ast::Item {
         attrs: vec![attr::mk_attr_outer(
             attr::mk_word_item(ast::Ident::new(sym::prelude_import, span)))],
         vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
         node: ast::ItemKind::Use(P(ast::UseTree {
-            prefix: ast::Path {
-                segments: iter::once(ast::Ident::with_dummy_span(kw::PathRoot))
-                    .chain(
-                        [name, "prelude", "v1"].iter().cloned()
-                            .map(ast::Ident::from_str)
-                    ).map(ast::PathSegment::from_ident).collect(),
-                span,
-            },
+            prefix: ast::Path { segments, span },
             kind: ast::UseTreeKind::Glob,
             span,
         })),
@@ -80,7 +82,65 @@ pub fn inject(
         ident: ast::Ident::invalid(),
         span,
         tokens: None,
-    }));
+    });
+
+    let prelude_import_item = if rust_2018 {
+        let hygienic_extern_crate = P(ast::Item {
+            attrs: vec![],
+            vis: respan(span, ast::VisibilityKind::Inherited),
+            node: ast::ItemKind::ExternCrate(alt_std_name),
+            ident: ast::Ident::new(name, span),
+            id: ast::DUMMY_NODE_ID,
+            span,
+            tokens: None,
+        });
+
+        // Use an anonymous const to hide `extern crate std as hygienic_std`
+        // FIXME: Once inter-crate hygiene exists, this can just be `use_item`.
+        P(ast::Item {
+            attrs: Vec::new(),
+            vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
+            node: ast::ItemKind::Const(
+                P(ast::Ty {
+                    id: ast::DUMMY_NODE_ID,
+                    node: ast::TyKind::Tup(Vec::new()),
+                    span,
+                }),
+                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(use_item),
+                                span,
+                            },
+                            ast::Stmt {
+                                id: ast::DUMMY_NODE_ID,
+                                node: ast::StmtKind::Item(hygienic_extern_crate),
+                                span,
+                            }
+                        ],
+                        span,
+                    }), None),
+                    span,
+                })
+            ),
+            id: ast::DUMMY_NODE_ID,
+            ident: ast::Ident::new(kw::Underscore, span),
+            span,
+            tokens: None,
+        })
+    } else {
+        // Have `extern crate std` at the root, so don't need to create a named
+        // extern crate item.
+        use_item
+    };
+
+    krate.module.items.insert(0, prelude_import_item);
 
-    (krate, Some(Symbol::intern(name)))
+    (krate, Some(name))
 }