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.
expand_panic<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, ) -> Box<dyn MacResult + 'cx>18 pub fn expand_panic<'cx>(
19     cx: &'cx mut ExtCtxt<'_>,
20     sp: Span,
21     tts: TokenStream,
22 ) -> Box<dyn MacResult + 'cx> {
23     let panic = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 };
24 
25     let sp = cx.with_call_site_ctxt(sp);
26 
27     MacEager::expr(
28         cx.expr(
29             sp,
30             ExprKind::MacCall(MacCall {
31                 path: Path {
32                     span: sp,
33                     segments: cx
34                         .std_path(&[sym::panic, panic])
35                         .into_iter()
36                         .map(|ident| PathSegment::from_ident(ident))
37                         .collect(),
38                     tokens: None,
39                 },
40                 args: P(MacArgs::Delimited(
41                     DelimSpan::from_single(sp),
42                     MacDelimiter::Parenthesis,
43                     tts,
44                 )),
45                 prior_type_ascription: None,
46             }),
47         ),
48     )
49 }
50 
use_panic_2021(mut span: Span) -> bool51 pub fn use_panic_2021(mut span: Span) -> bool {
52     // To determine the editon, we check the first span up the expansion
53     // stack that does not have #[allow_internal_unstable(edition_panic)].
54     // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.)
55     loop {
56         let expn = span.ctxt().outer_expn_data();
57         if let Some(features) = expn.allow_internal_unstable {
58             if features.iter().any(|&f| f == sym::edition_panic) {
59                 span = expn.call_site;
60                 continue;
61             }
62         }
63         break expn.edition >= Edition::Edition2021;
64     }
65 }
66