rustc_builtin_macros/
standard_library_imports.rs
1use rustc_ast::{self as ast, attr};
2use rustc_expand::base::{ExtCtxt, ResolverExpand};
3use rustc_expand::expand::ExpansionConfig;
4use rustc_feature::Features;
5use rustc_session::Session;
6use rustc_span::edition::Edition::*;
7use rustc_span::hygiene::AstPass;
8use rustc_span::{DUMMY_SP, Ident, Symbol, kw, sym};
9use thin_vec::thin_vec;
10
11pub fn inject(
12 krate: &mut ast::Crate,
13 pre_configured_attrs: &[ast::Attribute],
14 resolver: &mut dyn ResolverExpand,
15 sess: &Session,
16 features: &Features,
17) -> usize {
18 let orig_num_items = krate.items.len();
19 let edition = sess.psess.edition;
20
21 let names: &[Symbol] = if attr::contains_name(pre_configured_attrs, sym::no_core) {
23 return 0;
24 } else if attr::contains_name(pre_configured_attrs, sym::no_std) {
25 if attr::contains_name(pre_configured_attrs, sym::compiler_builtins) {
26 &[sym::core]
27 } else {
28 &[sym::core, sym::compiler_builtins]
29 }
30 } else {
31 &[sym::std]
32 };
33
34 let expn_id = resolver.expansion_for_ast_pass(
35 DUMMY_SP,
36 AstPass::StdImports,
37 &[sym::prelude_import],
38 None,
39 );
40 let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
41 let call_site = DUMMY_SP.with_call_site_ctxt(expn_id.to_expn_id());
42
43 let ecfg = ExpansionConfig::default("std_lib_injection".to_string(), features);
44 let cx = ExtCtxt::new(sess, ecfg, resolver, None);
45
46 for &name in names.iter().rev() {
48 let ident_span = if edition >= Edition2018 { span } else { call_site };
49 let item = if name == sym::compiler_builtins {
50 cx.item(
57 span,
58 Ident::new(kw::Underscore, ident_span),
59 thin_vec![],
60 ast::ItemKind::ExternCrate(Some(name)),
61 )
62 } else {
63 cx.item(
64 span,
65 Ident::new(name, ident_span),
66 thin_vec![cx.attr_word(sym::macro_use, span)],
67 ast::ItemKind::ExternCrate(None),
68 )
69 };
70 krate.items.insert(0, item);
71 }
72
73 let name = names[0];
76
77 let root = (edition == Edition2015).then_some(kw::PathRoot);
78
79 let import_path = root
80 .iter()
81 .chain(&[name, sym::prelude])
82 .chain(&[match edition {
83 Edition2015 => sym::rust_2015,
84 Edition2018 => sym::rust_2018,
85 Edition2021 => sym::rust_2021,
86 Edition2024 => sym::rust_2024,
87 }])
88 .map(|&symbol| Ident::new(symbol, span))
89 .collect();
90
91 let use_item = cx.item(
92 span,
93 Ident::empty(),
94 thin_vec![cx.attr_word(sym::prelude_import, span)],
95 ast::ItemKind::Use(ast::UseTree {
96 prefix: cx.path(span, import_path),
97 kind: ast::UseTreeKind::Glob,
98 span,
99 }),
100 );
101
102 krate.items.insert(0, use_item);
103 krate.items.len() - orig_num_items
104}