Skip to content

Commit ab6f663

Browse files
committed
Auto merge of rust-lang#132661 - matthiaskrgr:rollup-npytbl6, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#132259 (rustc_codegen_llvm: Add a new 'pc' option to branch-protection) - rust-lang#132409 (CI: switch 7 linux jobs to free runners) - rust-lang#132498 (Suggest fixing typos and let bindings at the same time) - rust-lang#132524 (chore(style): sync submodule exclusion list between tidy and rustfmt) - rust-lang#132567 (Properly suggest `E::assoc` when we encounter `E::Variant::assoc`) - rust-lang#132571 (add const_eval_select macro to reduce redundancy) - rust-lang#132637 (Do not filter empty lint passes & re-do CTFE pass) - rust-lang#132642 (Add documentation on `ast::Attribute`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents c12f4d1 + 6bc1b1b commit ab6f663

File tree

18 files changed

+478
-456
lines changed

18 files changed

+478
-456
lines changed

core/src/char/methods.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! impl char {}
22
33
use super::*;
4-
use crate::macros::const_panic;
4+
use crate::panic::const_panic;
55
use crate::slice;
66
use crate::str::from_utf8_unchecked_mut;
77
use crate::unicode::printable::is_printable;

core/src/ffi/c_str.rs

Lines changed: 48 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
use crate::cmp::Ordering;
44
use crate::error::Error;
55
use crate::ffi::c_char;
6+
use crate::intrinsics::const_eval_select;
67
use crate::iter::FusedIterator;
78
use crate::marker::PhantomData;
89
use crate::ptr::NonNull;
910
use crate::slice::memchr;
10-
use crate::{fmt, intrinsics, ops, slice, str};
11+
use crate::{fmt, ops, slice, str};
1112

1213
// FIXME: because this is doc(inline)d, we *have* to use intra-doc links because the actual link
1314
// depends on where the item is being documented. however, since this is libcore, we can't
@@ -411,37 +412,35 @@ impl CStr {
411412
#[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")]
412413
#[rustc_allow_const_fn_unstable(const_eval_select)]
413414
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
414-
#[inline]
415-
fn rt_impl(bytes: &[u8]) -> &CStr {
416-
// Chance at catching some UB at runtime with debug builds.
417-
debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);
418-
419-
// SAFETY: Casting to CStr is safe because its internal representation
420-
// is a [u8] too (safe only inside std).
421-
// Dereferencing the obtained pointer is safe because it comes from a
422-
// reference. Making a reference is then safe because its lifetime
423-
// is bound by the lifetime of the given `bytes`.
424-
unsafe { &*(bytes as *const [u8] as *const CStr) }
425-
}
426-
427-
const fn const_impl(bytes: &[u8]) -> &CStr {
428-
// Saturating so that an empty slice panics in the assert with a good
429-
// message, not here due to underflow.
430-
let mut i = bytes.len().saturating_sub(1);
431-
assert!(!bytes.is_empty() && bytes[i] == 0, "input was not nul-terminated");
432-
433-
// Ending nul byte exists, skip to the rest.
434-
while i != 0 {
435-
i -= 1;
436-
let byte = bytes[i];
437-
assert!(byte != 0, "input contained interior nul");
415+
const_eval_select!(
416+
@capture { bytes: &[u8] } -> &CStr:
417+
if const {
418+
// Saturating so that an empty slice panics in the assert with a good
419+
// message, not here due to underflow.
420+
let mut i = bytes.len().saturating_sub(1);
421+
assert!(!bytes.is_empty() && bytes[i] == 0, "input was not nul-terminated");
422+
423+
// Ending nul byte exists, skip to the rest.
424+
while i != 0 {
425+
i -= 1;
426+
let byte = bytes[i];
427+
assert!(byte != 0, "input contained interior nul");
428+
}
429+
430+
// SAFETY: See runtime cast comment below.
431+
unsafe { &*(bytes as *const [u8] as *const CStr) }
432+
} else {
433+
// Chance at catching some UB at runtime with debug builds.
434+
debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);
435+
436+
// SAFETY: Casting to CStr is safe because its internal representation
437+
// is a [u8] too (safe only inside std).
438+
// Dereferencing the obtained pointer is safe because it comes from a
439+
// reference. Making a reference is then safe because its lifetime
440+
// is bound by the lifetime of the given `bytes`.
441+
unsafe { &*(bytes as *const [u8] as *const CStr) }
438442
}
439-
440-
// SAFETY: See `rt_impl` cast.
441-
unsafe { &*(bytes as *const [u8] as *const CStr) }
442-
}
443-
444-
intrinsics::const_eval_select((bytes,), const_impl, rt_impl)
443+
)
445444
}
446445

447446
/// Returns the inner pointer to this C string.
@@ -735,29 +734,27 @@ impl AsRef<CStr> for CStr {
735734
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0"))]
736735
#[rustc_allow_const_fn_unstable(const_eval_select)]
737736
const unsafe fn strlen(ptr: *const c_char) -> usize {
738-
const fn strlen_ct(s: *const c_char) -> usize {
739-
let mut len = 0;
740-
741-
// SAFETY: Outer caller has provided a pointer to a valid C string.
742-
while unsafe { *s.add(len) } != 0 {
743-
len += 1;
744-
}
737+
const_eval_select!(
738+
@capture { s: *const c_char = ptr } -> usize:
739+
if const {
740+
let mut len = 0;
741+
742+
// SAFETY: Outer caller has provided a pointer to a valid C string.
743+
while unsafe { *s.add(len) } != 0 {
744+
len += 1;
745+
}
745746

746-
len
747-
}
747+
len
748+
} else {
749+
extern "C" {
750+
/// Provided by libc or compiler_builtins.
751+
fn strlen(s: *const c_char) -> usize;
752+
}
748753

749-
#[inline]
750-
fn strlen_rt(s: *const c_char) -> usize {
751-
extern "C" {
752-
/// Provided by libc or compiler_builtins.
753-
fn strlen(s: *const c_char) -> usize;
754+
// SAFETY: Outer caller has provided a pointer to a valid C string.
755+
unsafe { strlen(s) }
754756
}
755-
756-
// SAFETY: Outer caller has provided a pointer to a valid C string.
757-
unsafe { strlen(s) }
758-
}
759-
760-
intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt)
757+
)
761758
}
762759

763760
/// An iterator over the bytes of a [`CStr`], without the nul terminator.

core/src/intrinsics.rs

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2940,6 +2940,68 @@ where
29402940
unreachable!()
29412941
}
29422942

2943+
/// A macro to make it easier to invoke const_eval_select. Use as follows:
2944+
/// ```rust,ignore (just a macro example)
2945+
/// const_eval_select!(
2946+
/// @capture { arg1: i32 = some_expr, arg2: T = other_expr } -> U:
2947+
/// if const #[attributes_for_const_arm] {
2948+
/// // Compile-time code goes here.
2949+
/// } else #[attributes_for_runtime_arm] {
2950+
/// // Run-time code goes here.
2951+
/// }
2952+
/// )
2953+
/// ```
2954+
/// The `@capture` block declares which surrounding variables / expressions can be
2955+
/// used inside the `if const`.
2956+
/// Note that the two arms of this `if` really each become their own function, which is why the
2957+
/// macro supports setting attributes for those functions. The runtime function is always
2958+
/// markes as `#[inline]`.
2959+
///
2960+
/// See [`const_eval_select()`] for the rules and requirements around that intrinsic.
2961+
pub(crate) macro const_eval_select {
2962+
(
2963+
@capture { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? :
2964+
if const
2965+
$(#[$compiletime_attr:meta])* $compiletime:block
2966+
else
2967+
$(#[$runtime_attr:meta])* $runtime:block
2968+
) => {{
2969+
#[inline] // avoid the overhead of an extra fn call
2970+
$(#[$runtime_attr])*
2971+
fn runtime($($arg: $ty),*) $( -> $ret )? {
2972+
$runtime
2973+
}
2974+
2975+
#[inline] // prevent codegen on this function
2976+
$(#[$compiletime_attr])*
2977+
const fn compiletime($($arg: $ty),*) $( -> $ret )? {
2978+
// Don't warn if one of the arguments is unused.
2979+
$(let _ = $arg;)*
2980+
2981+
$compiletime
2982+
}
2983+
2984+
const_eval_select(($($val,)*), compiletime, runtime)
2985+
}},
2986+
// We support leaving away the `val` expressions for *all* arguments
2987+
// (but not for *some* arguments, that's too tricky).
2988+
(
2989+
@capture { $($arg:ident : $ty:ty),* $(,)? } $( -> $ret:ty )? :
2990+
if const
2991+
$(#[$compiletime_attr:meta])* $compiletime:block
2992+
else
2993+
$(#[$runtime_attr:meta])* $runtime:block
2994+
) => {
2995+
$crate::intrinsics::const_eval_select!(
2996+
@capture { $($arg : $ty = $arg),* } $(-> $ret)? :
2997+
if const
2998+
$(#[$compiletime_attr])* $compiletime
2999+
else
3000+
$(#[$runtime_attr])* $runtime
3001+
)
3002+
},
3003+
}
3004+
29433005
/// Returns whether the argument's value is statically known at
29443006
/// compile-time.
29453007
///
@@ -2982,7 +3044,7 @@ where
29823044
/// # Stability concerns
29833045
///
29843046
/// While it is safe to call, this intrinsic may behave differently in
2985-
/// a `const` context than otherwise. See the [`const_eval_select`]
3047+
/// a `const` context than otherwise. See the [`const_eval_select()`]
29863048
/// documentation for an explanation of the issues this can cause. Unlike
29873049
/// `const_eval_select`, this intrinsic isn't guaranteed to behave
29883050
/// deterministically even in a `const` context.
@@ -3868,14 +3930,15 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
38683930
fn miri_promise_symbolic_alignment(ptr: *const (), align: usize);
38693931
}
38703932

3871-
fn runtime(ptr: *const (), align: usize) {
3872-
// SAFETY: this call is always safe.
3873-
unsafe {
3874-
miri_promise_symbolic_alignment(ptr, align);
3933+
const_eval_select!(
3934+
@capture { ptr: *const (), align: usize}:
3935+
if const {
3936+
// Do nothing.
3937+
} else {
3938+
// SAFETY: this call is always safe.
3939+
unsafe {
3940+
miri_promise_symbolic_alignment(ptr, align);
3941+
}
38753942
}
3876-
}
3877-
3878-
const fn compiletime(_ptr: *const (), _align: usize) {}
3879-
3880-
const_eval_select((ptr, align), compiletime, runtime);
3943+
)
38813944
}

core/src/macros/mod.rs

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -12,54 +12,6 @@ macro_rules! panic {
1212
};
1313
}
1414

15-
/// Helper macro for panicking in a `const fn`.
16-
/// Invoke as:
17-
/// ```rust,ignore (just an example)
18-
/// core::macros::const_panic!("boring message", "flavored message {a} {b:?}", a: u32 = foo.len(), b: Something = bar);
19-
/// ```
20-
/// where the first message will be printed in const-eval,
21-
/// and the second message will be printed at runtime.
22-
// All uses of this macro are FIXME(const-hack).
23-
#[unstable(feature = "panic_internals", issue = "none")]
24-
#[doc(hidden)]
25-
pub macro const_panic {
26-
($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty = $val:expr),* $(,)?) => {{
27-
#[inline]
28-
#[track_caller]
29-
fn runtime($($arg: $ty),*) -> ! {
30-
$crate::panic!($runtime_msg);
31-
}
32-
33-
#[inline]
34-
#[track_caller]
35-
const fn compiletime($(_: $ty),*) -> ! {
36-
$crate::panic!($const_msg);
37-
}
38-
39-
// Wrap call to `const_eval_select` in a function so that we can
40-
// add the `rustc_allow_const_fn_unstable`. This is okay to do
41-
// because both variants will panic, just with different messages.
42-
#[rustc_allow_const_fn_unstable(const_eval_select)]
43-
#[inline(always)]
44-
#[track_caller]
45-
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_panic", since = "CURRENT_RUSTC_VERSION"))]
46-
const fn do_panic($($arg: $ty),*) -> ! {
47-
$crate::intrinsics::const_eval_select(($($arg),* ,), compiletime, runtime)
48-
}
49-
50-
do_panic($($val),*)
51-
}},
52-
// We support leaving away the `val` expressions for *all* arguments
53-
// (but not for *some* arguments, that's too tricky).
54-
($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty),* $(,)?) => {
55-
$crate::macros::const_panic!(
56-
$const_msg,
57-
$runtime_msg,
58-
$($arg: $ty = $arg),*
59-
)
60-
},
61-
}
62-
6315
/// Asserts that two expressions are equal to each other (using [`PartialEq`]).
6416
///
6517
/// Assertions are always checked in both debug and release builds, and cannot
@@ -244,19 +196,6 @@ pub macro assert_matches {
244196
},
245197
}
246198

247-
/// A version of `assert` that prints a non-formatting message in const contexts.
248-
///
249-
/// See [`const_panic!`].
250-
#[unstable(feature = "panic_internals", issue = "none")]
251-
#[doc(hidden)]
252-
pub macro const_assert {
253-
($condition: expr, $const_msg:literal, $runtime_msg:literal, $($arg:tt)*) => {{
254-
if !$crate::intrinsics::likely($condition) {
255-
$crate::macros::const_panic!($const_msg, $runtime_msg, $($arg)*)
256-
}
257-
}}
258-
}
259-
260199
/// A macro for defining `#[cfg]` match-like statements.
261200
///
262201
/// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of

core/src/num/f128.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
use crate::convert::FloatToInt;
1515
#[cfg(not(test))]
1616
use crate::intrinsics;
17-
use crate::macros::const_assert;
1817
use crate::mem;
1918
use crate::num::FpCategory;
19+
use crate::panic::const_assert;
2020

2121
/// Basic mathematical constants.
2222
#[unstable(feature = "f128", issue = "116909")]

core/src/num/f16.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
use crate::convert::FloatToInt;
1515
#[cfg(not(test))]
1616
use crate::intrinsics;
17-
use crate::macros::const_assert;
1817
use crate::mem;
1918
use crate::num::FpCategory;
19+
use crate::panic::const_assert;
2020

2121
/// Basic mathematical constants.
2222
#[unstable(feature = "f16", issue = "116909")]

core/src/num/f32.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
use crate::convert::FloatToInt;
1515
#[cfg(not(test))]
1616
use crate::intrinsics;
17-
use crate::macros::const_assert;
1817
use crate::mem;
1918
use crate::num::FpCategory;
19+
use crate::panic::const_assert;
2020

2121
/// The radix or base of the internal representation of `f32`.
2222
/// Use [`f32::RADIX`] instead.

core/src/num/f64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
use crate::convert::FloatToInt;
1515
#[cfg(not(test))]
1616
use crate::intrinsics;
17-
use crate::macros::const_assert;
1817
use crate::mem;
1918
use crate::num::FpCategory;
19+
use crate::panic::const_assert;
2020

2121
/// The radix or base of the internal representation of `f64`.
2222
/// Use [`f64::RADIX`] instead.

core/src/num/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
#![stable(feature = "rust1", since = "1.0.0")]
44

5-
use crate::macros::const_panic;
5+
use crate::panic::const_panic;
66
use crate::str::FromStr;
77
use crate::ub_checks::assert_unsafe_precondition;
88
use crate::{ascii, intrinsics, mem};

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy