Skip to main content

rustc_builtin_macros/
edition_panic.rs

1use rustc_ast::token::Delimiter;
2use rustc_ast::tokenstream::TokenStream;
3use rustc_expand::base::*;
4use rustc_span::edition::Edition;
5use rustc_span::{Span, sym};
6
7/// This expands to either
8/// - `$crate::panic::panic_2015!(...)` or
9/// - `$crate::panic::panic_2021!(...)`
10/// depending on the edition.
11///
12/// This is used for both std::panic!() and core::panic!().
13///
14/// `$crate` will refer to either the `std` or `core` crate depending on which
15/// one we're expanding from.
16pub(crate) fn expand_panic<'cx>(
17    cx: &'cx mut ExtCtxt<'_>,
18    sp: Span,
19    tts: TokenStream,
20) -> MacroExpanderResult<'cx> {
21    let mac = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 };
22    expand(mac, cx, sp, tts)
23}
24
25/// This expands to either
26/// - `$crate::panic::unreachable_2015!(...)` or
27/// - `$crate::panic::unreachable_2021!(...)`
28/// depending on the edition.
29pub(crate) fn expand_unreachable<'cx>(
30    cx: &'cx mut ExtCtxt<'_>,
31    sp: Span,
32    tts: TokenStream,
33) -> MacroExpanderResult<'cx> {
34    let mac = if use_panic_2021(sp) { sym::unreachable_2021 } else { sym::unreachable_2015 };
35    expand(mac, cx, sp, tts)
36}
37
38fn expand<'cx>(
39    mac: rustc_span::Symbol,
40    cx: &'cx ExtCtxt<'_>,
41    sp: Span,
42    tts: TokenStream,
43) -> MacroExpanderResult<'cx> {
44    let sp = cx.with_call_site_ctxt(sp);
45
46    ExpandResult::Ready(MacEager::expr(cx.expr_macro_call(
47        sp,
48        cx.macro_call(
49            sp,
50            cx.path(sp, cx.std_path(&[sym::panic, mac])),
51            Delimiter::Parenthesis,
52            tts,
53        ),
54    )))
55}
56
57pub(crate) fn use_panic_2021(mut span: Span) -> bool {
58    // To determine the edition, we check the first span up the expansion
59    // stack that does not have #[allow_internal_unstable(edition_panic)].
60    // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.)
61    loop {
62        let expn = span.ctxt().outer_expn_data();
63        if let Some(features) = expn.allow_internal_unstable
64            && features.contains(&sym::edition_panic)
65        {
66            span = expn.call_site;
67            continue;
68        }
69        break expn.edition >= Edition::Edition2021;
70    }
71}