]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_builtin_macros/src/edition_panic.rs
Rollup merge of #105359 - flba-eb:thread_local_key_sentinel_value, r=m-ou-se
[rust.git] / compiler / rustc_builtin_macros / src / edition_panic.rs
1 use rustc_ast::ptr::P;
2 use rustc_ast::tokenstream::{DelimSpan, TokenStream};
3 use rustc_ast::*;
4 use rustc_expand::base::*;
5 use rustc_span::edition::Edition;
6 use rustc_span::symbol::sym;
7 use rustc_span::Span;
8
9 /// This expands to either
10 /// - `$crate::panic::panic_2015!(...)` or
11 /// - `$crate::panic::panic_2021!(...)`
12 /// depending on the edition.
13 ///
14 /// This is used for both std::panic!() and core::panic!().
15 ///
16 /// `$crate` will refer to either the `std` or `core` crate depending on which
17 /// one we're expanding from.
18 pub fn expand_panic<'cx>(
19     cx: &'cx mut ExtCtxt<'_>,
20     sp: Span,
21     tts: TokenStream,
22 ) -> Box<dyn MacResult + 'cx> {
23     let mac = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 };
24     expand(mac, cx, sp, tts)
25 }
26
27 /// This expands to either
28 /// - `$crate::panic::unreachable_2015!(...)` or
29 /// - `$crate::panic::unreachable_2021!(...)`
30 /// depending on the edition.
31 pub fn expand_unreachable<'cx>(
32     cx: &'cx mut ExtCtxt<'_>,
33     sp: Span,
34     tts: TokenStream,
35 ) -> Box<dyn MacResult + 'cx> {
36     let mac = if use_panic_2021(sp) { sym::unreachable_2021 } else { sym::unreachable_2015 };
37     expand(mac, cx, sp, tts)
38 }
39
40 fn expand<'cx>(
41     mac: rustc_span::Symbol,
42     cx: &'cx mut ExtCtxt<'_>,
43     sp: Span,
44     tts: TokenStream,
45 ) -> Box<dyn MacResult + 'cx> {
46     let sp = cx.with_call_site_ctxt(sp);
47
48     MacEager::expr(
49         cx.expr(
50             sp,
51             ExprKind::MacCall(P(MacCall {
52                 path: Path {
53                     span: sp,
54                     segments: cx
55                         .std_path(&[sym::panic, mac])
56                         .into_iter()
57                         .map(|ident| PathSegment::from_ident(ident))
58                         .collect(),
59                     tokens: None,
60                 },
61                 args: P(DelimArgs {
62                     dspan: DelimSpan::from_single(sp),
63                     delim: MacDelimiter::Parenthesis,
64                     tokens: tts,
65                 }),
66                 prior_type_ascription: None,
67             })),
68         ),
69     )
70 }
71
72 pub fn use_panic_2021(mut span: Span) -> bool {
73     // To determine the edition, we check the first span up the expansion
74     // stack that does not have #[allow_internal_unstable(edition_panic)].
75     // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.)
76     loop {
77         let expn = span.ctxt().outer_expn_data();
78         if let Some(features) = expn.allow_internal_unstable {
79             if features.iter().any(|&f| f == sym::edition_panic) {
80                 span = expn.call_site;
81                 continue;
82             }
83         }
84         break expn.edition >= Edition::Edition2021;
85     }
86 }