diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-07-18 22:29:07 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-07-27 13:56:54 +0300 |
| commit | 4d535bdf59136f69b55107caaa0f5492b5e84d2d (patch) | |
| tree | 656d97ef9c892f9671aa8aae29c990da3662c61b /src/libsyntax_ext | |
| parent | f6eda9937956667c01bc567ab4a9bd6a19f71635 (diff) | |
| download | rust-4d535bdf59136f69b55107caaa0f5492b5e84d2d.tar.gz rust-4d535bdf59136f69b55107caaa0f5492b5e84d2d.zip | |
Move standard library injection into libsyntax_ext
Diffstat (limited to 'src/libsyntax_ext')
| -rw-r--r-- | src/libsyntax_ext/lib.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax_ext/standard_library_imports.rs | 95 |
2 files changed, 96 insertions, 0 deletions
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index cd0d0886239..f49c75d7424 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -43,6 +43,7 @@ mod trace_macros; pub mod plugin_macro_defs; pub mod proc_macro_decls; +pub mod standard_library_imports; pub mod test_harness; pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, edition: Edition) { diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs new file mode 100644 index 00000000000..81bb32d79a2 --- /dev/null +++ b/src/libsyntax_ext/standard_library_imports.rs @@ -0,0 +1,95 @@ +use syntax::{ast, attr}; +use syntax::edition::Edition; +use syntax::ext::hygiene::{ExpnId, MacroKind}; +use syntax::ptr::P; +use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan}; +use syntax::symbol::{Ident, Symbol, kw, sym}; +use syntax::tokenstream::TokenStream; +use syntax_pos::DUMMY_SP; + +use std::iter; + +pub fn inject( + mut krate: ast::Crate, alt_std_name: Option<&str>, 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) { + return (krate, None); + } else if attr::contains_name(&krate.attrs, sym::no_std) { + if attr::contains_name(&krate.attrs, sym::compiler_builtins) { + &["core"] + } else { + &["core", "compiler_builtins"] + } + } else { + &["std"] + }; + + // .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_empty_ctxt(orig_name_sym); + let (rename, orig_name) = if rust_2018 { + (orig_name_ident.gensym(), Some(orig_name_sym)) + } else { + (orig_name_ident, None) + }; + krate.module.items.insert(0, P(ast::Item { + attrs: vec![attr::mk_attr_outer( + DUMMY_SP, + attr::mk_attr_id(), + attr::mk_word_item(ast::Ident::with_empty_ctxt(sym::macro_use)) + )], + vis: dummy_spanned(ast::VisibilityKind::Inherited), + node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)), + ident: rename, + id: ast::DUMMY_NODE_ID, + span: DUMMY_SP, + tokens: None, + })); + } + + // the crates have been injected, the assumption is that the first one is the one with + // the prelude. + let name = names[0]; + + let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable( + ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition, + [sym::prelude_import][..].into(), + )); + + krate.module.items.insert(0, P(ast::Item { + attrs: vec![ast::Attribute { + style: ast::AttrStyle::Outer, + path: ast::Path::from_ident(ast::Ident::new(sym::prelude_import, span)), + tokens: TokenStream::empty(), + id: attr::mk_attr_id(), + is_sugared_doc: false, + 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_empty_ctxt(kw::PathRoot)) + .chain( + [name, "prelude", "v1"].iter().cloned() + .map(ast::Ident::from_str) + ).map(ast::PathSegment::from_ident).collect(), + span, + }, + kind: ast::UseTreeKind::Glob, + span, + })), + id: ast::DUMMY_NODE_ID, + ident: ast::Ident::invalid(), + span, + tokens: None, + })); + + (krate, Some(Symbol::intern(name))) +} |
