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(sp, cx.std_path(sp, &[sym::panic, mac]), Delimiter::Parenthesis, tts),
49    )))
50}
51
52pub(crate) fn use_panic_2021(mut span: Span) -> bool {
53    // To determine the edition, we check the first span up the expansion
54    // stack that does not have #[allow_internal_unstable(edition_panic)].
55    // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.)
56    loop {
57        let expn = span.ctxt().outer_expn_data();
58        if let Some(features) = expn.allow_internal_unstable
59            && features.contains(&sym::edition_panic)
60        {
61            span = expn.call_site;
62            continue;
63        }
64        break expn.edition >= Edition::Edition2021;
65    }
66}