diff options
Diffstat (limited to 'src/libsyntax_ext/standard_library_imports.rs')
| -rw-r--r-- | src/libsyntax_ext/standard_library_imports.rs | 130 |
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)) } |
