Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 39 additions & 18 deletions compiler/rustc_builtin_macros/src/edition_panic.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,35 @@
use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::*;
use rustc_expand::base::*;
use rustc_span::edition::Edition;
use rustc_span::{Span, sym};
use rustc_span::{Span, Symbol, sym};

// Use an enum to ensure that no new macro calls are added without also updating the message in the
// optimized path below.
enum InnerCall {
Panic2015,
Panic2021,
Unreachable2015,
Unreachable2021,
}

impl InnerCall {
fn symbol(&self) -> Symbol {
match self {
Self::Panic2015 => sym::panic_2015,
Self::Panic2021 => sym::panic_2021,
Self::Unreachable2015 => sym::unreachable_2015,
Self::Unreachable2021 => sym::unreachable_2021,
}
}
}

/// This expands to either
/// - `$crate::panic::panic_2015!(...)` or
/// - `$crate::panic::panic_2021!(...)`
/// depending on the edition.
/// depending on the edition. If the entire message is known at compile time,
/// `core::panicking::panic` may be called as an optimization.
///
/// This is used for both std::panic!() and core::panic!().
///
Expand All @@ -19,50 +40,50 @@ pub(crate) fn expand_panic<'cx>(
sp: Span,
tts: TokenStream,
) -> MacroExpanderResult<'cx> {
let mac = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 };
let mac = if use_panic_2021(sp) { InnerCall::Panic2021 } else { InnerCall::Panic2015 };
expand(mac, cx, sp, tts)
}

/// This expands to either
/// - `$crate::panic::unreachable_2015!(...)` or
/// - `$crate::panic::unreachable_2021!(...)`
/// depending on the edition.
/// depending on the edition. If the entire message is known at compile time,
/// `core::panicking::panic` may be called as an optimization.
pub(crate) fn expand_unreachable<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> MacroExpanderResult<'cx> {
let mac = if use_panic_2021(sp) { sym::unreachable_2021 } else { sym::unreachable_2015 };
let mac =
if use_panic_2021(sp) { InnerCall::Unreachable2021 } else { InnerCall::Unreachable2015 };
expand(mac, cx, sp, tts)
}

fn expand<'cx>(
mac: rustc_span::Symbol,
mac: InnerCall,
cx: &'cx ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> MacroExpanderResult<'cx> {
let sp = cx.with_call_site_ctxt(sp);

ExpandResult::Ready(MacEager::expr(
cx.expr(
cx.expr_macro_call(
sp,
ExprKind::MacCall(Box::new(MacCall {
path: Path {
cx.macro_call(
sp,
Path {
span: sp,
segments: cx
.std_path(&[sym::panic, mac])
.std_path(&[sym::panic, mac.symbol()])
.into_iter()
.map(|ident| PathSegment::from_ident(ident))
.map(PathSegment::from_ident)
.collect(),
tokens: None,
},
args: Box::new(DelimArgs {
dspan: DelimSpan::from_single(sp),
delim: Delimiter::Parenthesis,
tokens: tts,
}),
})),
Delimiter::Parenthesis,
tts,
),
),
))
}
Expand Down
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
#![feature(strict_provenance_lints)]
#![feature(super_let)]
#![feature(trait_alias)]
#![feature(transparent_unions)]
#![feature(try_blocks)]
Expand Down
7 changes: 4 additions & 3 deletions library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#[doc = include_str!("panic.md")]
#[macro_export]
#[rustc_builtin_macro(core_panic)]
#[allow_internal_unstable(edition_panic)]
#[allow_internal_unstable(edition_panic, panic_internals)]
#[stable(feature = "core", since = "1.6.0")]
#[rustc_diagnostic_item = "core_panic_macro"]
macro_rules! panic {
// Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021`
// depending on the edition of the caller.
// depending on the edition of the caller. If the entire message is known at compile time,
// `core::panicking::panic` may be called as an optimization.
($($arg:tt)*) => {
/* compiler built-in */
};
Expand Down Expand Up @@ -705,7 +706,7 @@ macro_rules! writeln {
/// ```
#[macro_export]
#[rustc_builtin_macro(unreachable)]
#[allow_internal_unstable(edition_panic)]
#[allow_internal_unstable(edition_panic, panic_internals)]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "unreachable_macro"]
macro_rules! unreachable {
Expand Down
8 changes: 6 additions & 2 deletions library/core/src/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub macro panic_2015 {

#[doc(hidden)]
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
#[allow_internal_unstable(panic_internals, const_format_args)]
#[allow_internal_unstable(panic_internals, const_format_args, super_let)]
#[rustc_diagnostic_item = "core_panic_2021_macro"]
#[rustc_macro_transparency = "semitransparent"]
pub macro panic_2021 {
Expand All @@ -59,7 +59,11 @@ pub macro panic_2021 {
($($t:tt)+) => ({
// Semicolon to prevent temporaries inside the formatting machinery from
// being considered alive in the caller after the panic_fmt call.
$crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
super let args = $crate::const_format_args!($($t)+);
if let $crate::option::Option::Some(s) = args.as_str() {
$crate::panicking::panic(s);
}
$crate::panicking::panic_fmt(args);
}),
}

Expand Down
5 changes: 3 additions & 2 deletions library/std/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
#[macro_export]
#[rustc_builtin_macro(std_panic)]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(edition_panic)]
#[allow_internal_unstable(edition_panic, panic_internals)]
#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")]
macro_rules! panic {
// Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021`
// depending on the edition of the caller.
// depending on the edition of the caller. If the entire message is known at compile time,
// `core::panicking::panic` may be called as an optimization.
($($arg:tt)*) => {
/* compiler built-in */
};
Expand Down
24 changes: 16 additions & 8 deletions src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub struct IncompatibleMsrv {
msrv: Msrv,
availability_cache: FxHashMap<(DefId, bool), Availability>,
check_in_tests: bool,
core_crate: Option<CrateNum>,
stdlib_crates: Vec<CrateNum>,

// The most recently called path. Used to skip checking the path after it's
// been checked when visiting the call expression.
Expand All @@ -96,11 +96,15 @@ impl IncompatibleMsrv {
msrv: conf.msrv,
availability_cache: FxHashMap::default(),
check_in_tests: conf.check_incompatible_msrv_in_tests,
core_crate: tcx
stdlib_crates: tcx
.crates(())
.iter()
.find(|krate| tcx.crate_name(**krate) == sym::core)
.copied(),
.filter(|krate| {
let name = tcx.crate_name(**krate);
name == sym::core || name == sym::alloc || name == sym::std
})
.copied()
.collect(),
called_path: None,
}
}
Expand Down Expand Up @@ -162,10 +166,14 @@ impl IncompatibleMsrv {
// Intentionally not using `.from_expansion()`, since we do still care about macro expansions
return;
}
// Functions coming from `core` while expanding a macro such as `assert*!()` get to cheat too: the
// macros may have existed prior to the checked MSRV, but their expansion with a recent compiler
// might use recent functions or methods. Compiling with an older compiler would not use those.
if Some(def_id.krate) == self.core_crate && expn_data.macro_def_id.map(|did| did.krate) == self.core_crate {
// Functions coming from standard library crates while expanding a macro such as
// `assert*!()` get to cheat too: the macros may have existed prior to the checked MSRV, but
// their expansion with a recent compiler might use recent functions or methods. Compiling
// with an older compiler would not use those.
if self.stdlib_crates.contains(&def_id.krate)
&& let Some(did) = expn_data.macro_def_id
&& self.stdlib_crates.contains(&did.krate)
{
return;
}

Expand Down
8 changes: 5 additions & 3 deletions src/tools/miri/tests/panic/panic1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ panicking from libstd
stack backtrace:
0: std::panicking::panic_handler
at RUSTLIB/std/src/panicking.rs:LL:CC
1: std::rt::panic_fmt
1: core::panicking::panic_fmt
at RUSTLIB/core/src/panicking.rs:LL:CC
2: main
2: core::panicking::panic
at RUSTLIB/core/src/panicking.rs:LL:CC
3: main
at tests/panic/panic1.rs:LL:CC
3: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
4: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
at RUSTLIB/core/src/ops/function.rs:LL:CC
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Loading