]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_builtin_macros/src/edition_panic.rs
New upstream version 1.61.0+dfsg1
[rustc.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(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(MacArgs::Delimited(
62 DelimSpan::from_single(sp),
63 MacDelimiter::Parenthesis,
64 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 }