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    // the first name in this list is the crate name of the crate with the prelude
22    let name: 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        sym::core
26    } else {
27        sym::std
28    };
29
30    let expn_id = resolver.expansion_for_ast_pass(
31        DUMMY_SP,
32        AstPass::StdImports,
33        &[sym::prelude_import],
34        None,
35    );
36    let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
37    let call_site = DUMMY_SP.with_call_site_ctxt(expn_id.to_expn_id());
38
39    let ecfg = ExpansionConfig::default(sym::std_lib_injection, features);
40    let cx = ExtCtxt::new(sess, ecfg, resolver, None);
41
42    let ident_span = if edition >= Edition2018 { span } else { call_site };
43
44    let item = cx.item(
45        span,
46        thin_vec![cx.attr_word(sym::macro_use, span)],
47        ast::ItemKind::ExternCrate(None, Ident::new(name, ident_span)),
48    );
49
50    let root = (edition == Edition2015).then_some(kw::PathRoot);
51
52    let import_path = root
53        .iter()
54        .chain(&[name, sym::prelude])
55        .chain(&[match edition {
56            Edition2015 => sym::rust_2015,
57            Edition2018 => sym::rust_2018,
58            Edition2021 => sym::rust_2021,
59            Edition2024 => sym::rust_2024,
60            EditionFuture => sym::rust_future,
61        }])
62        .map(|&symbol| Ident::new(symbol, span))
63        .collect();
64
65    // Inject the relevant crate's prelude.
66    let use_item = cx.item(
67        span,
68        thin_vec![cx.attr_word(sym::prelude_import, span)],
69        ast::ItemKind::Use(ast::UseTree {
70            prefix: cx.path(span, import_path),
71            kind: ast::UseTreeKind::Glob,
72            span,
73        }),
74    );
75
76    krate.items.splice(0..0, [item, use_item]);
77    krate.items.len() - orig_num_items
78}