diff options
| author | bors <bors@rust-lang.org> | 2021-09-23 02:10:26 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-09-23 02:10:26 +0000 |
| commit | 67365d64bcdfeae1334bf2ff49587c27d1c973f0 (patch) | |
| tree | e675fccc48356eac3a83e78ae3894491a6c0ded5 /library | |
| parent | 30278d3cf92b581550933546370443a5d5700002 (diff) | |
| parent | 2efa9d796981163031a7478734fee561dc3a6da0 (diff) | |
Auto merge of #89139 - camsteffen:write-perf, r=Mark-Simulacrum
Use ZST for fmt unsafety as suggested here - https://github.com/rust-lang/rust/pull/83302#issuecomment-923529151.
Diffstat (limited to 'library')
| -rw-r--r-- | library/core/src/fmt/mod.rs | 53 | ||||
| -rw-r--r-- | library/core/src/panicking.rs | 5 |
2 files changed, 45 insertions, 13 deletions
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 166a8e3f28a..8fa941c42fc 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -265,6 +265,26 @@ pub struct ArgumentV1<'a> { formatter: fn(&Opaque, &mut Formatter<'_>) -> Result, } +/// This struct represents the unsafety of constructing an `Arguments`. +/// It exists, rather than an unsafe function, in order to simplify the expansion +/// of `format_args!(..)` and reduce the scope of the `unsafe` block. +#[allow(missing_debug_implementations)] +#[doc(hidden)] +#[non_exhaustive] +#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] +pub struct UnsafeArg; + +impl UnsafeArg { + /// See documentation where `UnsafeArg` is required to know when it is safe to + /// create and use `UnsafeArg`. + #[doc(hidden)] + #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] + #[inline(always)] + pub unsafe fn new() -> Self { + Self + } +} + // This guarantees a single stable value for the function pointer associated with // indices/counts in the formatting infrastructure. // @@ -337,10 +357,7 @@ impl<'a> Arguments<'a> { #[inline] #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")] - pub const unsafe fn new_v1( - pieces: &'a [&'static str], - args: &'a [ArgumentV1<'a>], - ) -> Arguments<'a> { + pub const fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { if pieces.len() < args.len() || pieces.len() > args.len() + 1 { panic!("invalid args"); } @@ -348,11 +365,29 @@ impl<'a> Arguments<'a> { } /// This function is used to specify nonstandard formatting parameters. - /// The `pieces` array must be at least as long as `fmt` to construct - /// a valid Arguments structure. Also, any `Count` within `fmt` that is - /// `CountIsParam` or `CountIsNextParam` has to point to an argument - /// created with `argumentusize`. However, failing to do so doesn't cause - /// unsafety, but will ignore invalid . + /// + /// An `UnsafeArg` is required because the following invariants must be held + /// in order for this function to be safe: + /// 1. The `pieces` slice must be at least as long as `fmt`. + /// 2. Every [`rt::v1::Argument::position`] value within `fmt` must be a + /// valid index of `args`. + /// 3. Every [`Count::Param`] within `fmt` must contain a valid index of + /// `args`. + #[cfg(not(bootstrap))] + #[doc(hidden)] + #[inline] + #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] + #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")] + pub const fn new_v1_formatted( + pieces: &'a [&'static str], + args: &'a [ArgumentV1<'a>], + fmt: &'a [rt::v1::Argument], + _unsafe_arg: UnsafeArg, + ) -> Arguments<'a> { + Arguments { pieces, fmt: Some(fmt), args } + } + + #[cfg(bootstrap)] #[doc(hidden)] #[inline] #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index a6aa4bf43c8..6d3ec6ae861 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -47,10 +47,7 @@ pub fn panic(expr: &'static str) -> ! { // truncation and padding (even though none is used here). Using // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the // output binary, saving up to a few kilobytes. - panic_fmt( - // SAFETY: Arguments::new_v1 is safe with exactly one str and zero args - unsafe { fmt::Arguments::new_v1(&[expr], &[]) }, - ); + panic_fmt(fmt::Arguments::new_v1(&[expr], &[])); } #[inline] |
