Rollup merge of #110766 - m-ou-se:fmt-rt, r=jyn514
More core::fmt::rt cleanup. - Removes the `V1` suffix from the `Argument` and `Flag` types. - Moves more of the format_args lang items into the `core::fmt::rt` module. (The only remaining lang item in `core::fmt` is `Arguments` itself, which is a public type.) Part of https://github.com/rust-lang/rust/issues/99012 Follow-up to https://github.com/rust-lang/rust/pull/110616
This commit is contained in:
commit
cf911ac757
@ -186,7 +186,7 @@ enum ArgumentType {
|
|||||||
/// Generates:
|
/// Generates:
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// <core::fmt::ArgumentV1>::new_…(arg)
|
/// <core::fmt::Argument>::new_…(arg)
|
||||||
/// ```
|
/// ```
|
||||||
fn make_argument<'hir>(
|
fn make_argument<'hir>(
|
||||||
ctx: &mut LoweringContext<'_, 'hir>,
|
ctx: &mut LoweringContext<'_, 'hir>,
|
||||||
@ -327,7 +327,7 @@ fn make_format_spec<'hir>(
|
|||||||
None => sym::Unknown,
|
None => sym::Unknown,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// This needs to match `FlagV1` in library/core/src/fmt/mod.rs.
|
// This needs to match `Flag` in library/core/src/fmt/rt.rs.
|
||||||
let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
|
let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
|
||||||
| ((sign == Some(FormatSign::Minus)) as u32) << 1
|
| ((sign == Some(FormatSign::Minus)) as u32) << 1
|
||||||
| (alternate as u32) << 2
|
| (alternate as u32) << 2
|
||||||
@ -438,7 +438,7 @@ fn expand_format_args<'hir>(
|
|||||||
// If the args array contains exactly all the original arguments once,
|
// If the args array contains exactly all the original arguments once,
|
||||||
// in order, we can use a simple array instead of a `match` construction.
|
// in order, we can use a simple array instead of a `match` construction.
|
||||||
// However, if there's a yield point in any argument except the first one,
|
// However, if there's a yield point in any argument except the first one,
|
||||||
// we don't do this, because an ArgumentV1 cannot be kept across yield points.
|
// we don't do this, because an Argument cannot be kept across yield points.
|
||||||
//
|
//
|
||||||
// This is an optimization, speeding up compilation about 1-2% in some cases.
|
// This is an optimization, speeding up compilation about 1-2% in some cases.
|
||||||
// See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609
|
// See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609
|
||||||
@ -449,9 +449,9 @@ fn expand_format_args<'hir>(
|
|||||||
let args = if use_simple_array {
|
let args = if use_simple_array {
|
||||||
// Generate:
|
// Generate:
|
||||||
// &[
|
// &[
|
||||||
// <core::fmt::ArgumentV1>::new_display(&arg0),
|
// <core::fmt::Argument>::new_display(&arg0),
|
||||||
// <core::fmt::ArgumentV1>::new_lower_hex(&arg1),
|
// <core::fmt::Argument>::new_lower_hex(&arg1),
|
||||||
// <core::fmt::ArgumentV1>::new_debug(&arg2),
|
// <core::fmt::Argument>::new_debug(&arg2),
|
||||||
// …
|
// …
|
||||||
// ]
|
// ]
|
||||||
let elements: Vec<_> = arguments
|
let elements: Vec<_> = arguments
|
||||||
@ -477,9 +477,9 @@ fn expand_format_args<'hir>(
|
|||||||
// Generate:
|
// Generate:
|
||||||
// &match (&arg0, &arg1, &…) {
|
// &match (&arg0, &arg1, &…) {
|
||||||
// args => [
|
// args => [
|
||||||
// <core::fmt::ArgumentV1>::new_display(args.0),
|
// <core::fmt::Argument>::new_display(args.0),
|
||||||
// <core::fmt::ArgumentV1>::new_lower_hex(args.1),
|
// <core::fmt::Argument>::new_lower_hex(args.1),
|
||||||
// <core::fmt::ArgumentV1>::new_debug(args.0),
|
// <core::fmt::Argument>::new_debug(args.0),
|
||||||
// …
|
// …
|
||||||
// ]
|
// ]
|
||||||
// }
|
// }
|
||||||
|
@ -296,7 +296,7 @@ macro_rules! error {
|
|||||||
diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span)));
|
diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span)));
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
_ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => ccx
|
_ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentMethods) => ccx
|
||||||
.tcx
|
.tcx
|
||||||
.sess
|
.sess
|
||||||
.create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }),
|
.create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }),
|
||||||
|
@ -129,8 +129,7 @@
|
|||||||
Any,
|
Any,
|
||||||
Arc,
|
Arc,
|
||||||
Argument,
|
Argument,
|
||||||
ArgumentV1,
|
ArgumentMethods,
|
||||||
ArgumentV1Methods,
|
|
||||||
Arguments,
|
Arguments,
|
||||||
AsMut,
|
AsMut,
|
||||||
AsRef,
|
AsRef,
|
||||||
|
@ -251,223 +251,6 @@ pub fn new(buf: &'a mut (dyn Write + 'a)) -> Formatter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB. Argument is essentially an optimized partially applied formatting function,
|
|
||||||
// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`.
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
type Opaque;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This struct represents the generic "argument" which is taken by the Xprintf
|
|
||||||
/// family of functions. It contains a function to format the given value. At
|
|
||||||
/// compile time it is ensured that the function and the value have the correct
|
|
||||||
/// types, and then this struct is used to canonicalize arguments to one type.
|
|
||||||
#[lang = "format_argument"]
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
#[allow(missing_debug_implementations)]
|
|
||||||
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct ArgumentV1<'a> {
|
|
||||||
value: &'a Opaque,
|
|
||||||
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.
|
|
||||||
#[lang = "format_unsafe_arg"]
|
|
||||||
#[allow(missing_debug_implementations)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
|
|
||||||
pub struct UnsafeArg {
|
|
||||||
_private: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
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 { _private: () }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This guarantees a single stable value for the function pointer associated with
|
|
||||||
// indices/counts in the formatting infrastructure.
|
|
||||||
//
|
|
||||||
// Note that a function defined as such would not be correct as functions are
|
|
||||||
// always tagged unnamed_addr with the current lowering to LLVM IR, so their
|
|
||||||
// address is not considered important to LLVM and as such the as_usize cast
|
|
||||||
// could have been miscompiled. In practice, we never call as_usize on non-usize
|
|
||||||
// containing data (as a matter of static generation of the formatting
|
|
||||||
// arguments), so this is merely an additional check.
|
|
||||||
//
|
|
||||||
// We primarily want to ensure that the function pointer at `USIZE_MARKER` has
|
|
||||||
// an address corresponding *only* to functions that also take `&usize` as their
|
|
||||||
// first argument. The read_volatile here ensures that we can safely ready out a
|
|
||||||
// usize from the passed reference and that this address does not point at a
|
|
||||||
// non-usize taking function.
|
|
||||||
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
|
|
||||||
static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| {
|
|
||||||
// SAFETY: ptr is a reference
|
|
||||||
let _v: usize = unsafe { crate::ptr::read_volatile(ptr) };
|
|
||||||
loop {}
|
|
||||||
};
|
|
||||||
|
|
||||||
macro_rules! arg_new {
|
|
||||||
($f: ident, $t: ident) => {
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
|
|
||||||
#[inline]
|
|
||||||
pub fn $f<'b, T: $t>(x: &'b T) -> ArgumentV1<'_> {
|
|
||||||
Self::new(x, $t::fmt)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustc_diagnostic_item = "ArgumentV1Methods"]
|
|
||||||
impl<'a> ArgumentV1<'a> {
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
|
|
||||||
#[inline]
|
|
||||||
pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {
|
|
||||||
// SAFETY: `mem::transmute(x)` is safe because
|
|
||||||
// 1. `&'b T` keeps the lifetime it originated with `'b`
|
|
||||||
// (so as to not have an unbounded lifetime)
|
|
||||||
// 2. `&'b T` and `&'b Opaque` have the same memory layout
|
|
||||||
// (when `T` is `Sized`, as it is here)
|
|
||||||
// `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
|
|
||||||
// and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI
|
|
||||||
// (as long as `T` is `Sized`)
|
|
||||||
unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } }
|
|
||||||
}
|
|
||||||
|
|
||||||
arg_new!(new_display, Display);
|
|
||||||
arg_new!(new_debug, Debug);
|
|
||||||
arg_new!(new_octal, Octal);
|
|
||||||
arg_new!(new_lower_hex, LowerHex);
|
|
||||||
arg_new!(new_upper_hex, UpperHex);
|
|
||||||
arg_new!(new_pointer, Pointer);
|
|
||||||
arg_new!(new_binary, Binary);
|
|
||||||
arg_new!(new_lower_exp, LowerExp);
|
|
||||||
arg_new!(new_upper_exp, UpperExp);
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
|
|
||||||
pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
|
|
||||||
ArgumentV1::new(x, USIZE_MARKER)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_usize(&self) -> Option<usize> {
|
|
||||||
// We are type punning a bit here: USIZE_MARKER only takes an &usize but
|
|
||||||
// formatter takes an &Opaque. Rust understandably doesn't think we should compare
|
|
||||||
// the function pointers if they don't have the same signature, so we cast to
|
|
||||||
// usizes to tell it that we just want to compare addresses.
|
|
||||||
if self.formatter as usize == USIZE_MARKER as usize {
|
|
||||||
// SAFETY: The `formatter` field is only set to USIZE_MARKER if
|
|
||||||
// the value is a usize, so this is safe
|
|
||||||
Some(unsafe { *(self.value as *const _ as *const usize) })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// flags available in the v1 format of format_args
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
enum FlagV1 {
|
|
||||||
SignPlus,
|
|
||||||
SignMinus,
|
|
||||||
Alternate,
|
|
||||||
SignAwareZeroPad,
|
|
||||||
DebugLowerHex,
|
|
||||||
DebugUpperHex,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Arguments<'a> {
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "fmt_internals", issue = "none")]
|
|
||||||
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
|
|
||||||
pub const fn new_const(pieces: &'a [&'static str]) -> Self {
|
|
||||||
if pieces.len() > 1 {
|
|
||||||
panic!("invalid args");
|
|
||||||
}
|
|
||||||
Arguments { pieces, fmt: None, args: &[] }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// When using the format_args!() macro, this function is used to generate the
|
|
||||||
/// Arguments structure.
|
|
||||||
#[cfg(not(bootstrap))]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
|
|
||||||
pub 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");
|
|
||||||
}
|
|
||||||
Arguments { pieces, fmt: None, args }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(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(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
|
|
||||||
if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
|
|
||||||
panic!("invalid args");
|
|
||||||
}
|
|
||||||
Arguments { pieces, fmt: None, args }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This function is used to specify nonstandard formatting parameters.
|
|
||||||
///
|
|
||||||
/// 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::Placeholder::position` value within `fmt` must be a valid index of `args`.
|
|
||||||
/// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
|
|
||||||
pub fn new_v1_formatted(
|
|
||||||
pieces: &'a [&'static str],
|
|
||||||
args: &'a [ArgumentV1<'a>],
|
|
||||||
fmt: &'a [rt::Placeholder],
|
|
||||||
_unsafe_arg: UnsafeArg,
|
|
||||||
) -> Arguments<'a> {
|
|
||||||
Arguments { pieces, fmt: Some(fmt), args }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Estimates the length of the formatted text.
|
|
||||||
///
|
|
||||||
/// This is intended to be used for setting initial `String` capacity
|
|
||||||
/// when using `format!`. Note: this is neither the lower nor upper bound.
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[inline]
|
|
||||||
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
|
|
||||||
pub fn estimated_capacity(&self) -> usize {
|
|
||||||
let pieces_length: usize = self.pieces.iter().map(|x| x.len()).sum();
|
|
||||||
|
|
||||||
if self.args.is_empty() {
|
|
||||||
pieces_length
|
|
||||||
} else if !self.pieces.is_empty() && self.pieces[0].is_empty() && pieces_length < 16 {
|
|
||||||
// If the format string starts with an argument,
|
|
||||||
// don't preallocate anything, unless length
|
|
||||||
// of pieces is significant.
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
// There are some arguments, so any additional push
|
|
||||||
// will reallocate the string. To avoid that,
|
|
||||||
// we're "pre-doubling" the capacity here.
|
|
||||||
pieces_length.checked_mul(2).unwrap_or(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This structure represents a safely precompiled version of a format string
|
/// This structure represents a safely precompiled version of a format string
|
||||||
/// and its arguments. This cannot be generated at runtime because it cannot
|
/// and its arguments. This cannot be generated at runtime because it cannot
|
||||||
/// safely be done, so no constructors are given and the fields are private
|
/// safely be done, so no constructors are given and the fields are private
|
||||||
@ -502,7 +285,82 @@ pub struct Arguments<'a> {
|
|||||||
|
|
||||||
// Dynamic arguments for interpolation, to be interleaved with string
|
// Dynamic arguments for interpolation, to be interleaved with string
|
||||||
// pieces. (Every argument is preceded by a string piece.)
|
// pieces. (Every argument is preceded by a string piece.)
|
||||||
args: &'a [ArgumentV1<'a>],
|
args: &'a [rt::Argument<'a>],
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used by the format_args!() macro to create a fmt::Arguments object.
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[unstable(feature = "fmt_internals", issue = "none")]
|
||||||
|
impl<'a> Arguments<'a> {
|
||||||
|
#[inline]
|
||||||
|
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
|
||||||
|
pub const fn new_const(pieces: &'a [&'static str]) -> Self {
|
||||||
|
if pieces.len() > 1 {
|
||||||
|
panic!("invalid args");
|
||||||
|
}
|
||||||
|
Arguments { pieces, fmt: None, args: &[] }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// When using the format_args!() macro, this function is used to generate the
|
||||||
|
/// Arguments structure.
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[inline]
|
||||||
|
pub fn new_v1(pieces: &'a [&'static str], args: &'a [rt::Argument<'a>]) -> Arguments<'a> {
|
||||||
|
if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
|
||||||
|
panic!("invalid args");
|
||||||
|
}
|
||||||
|
Arguments { pieces, fmt: None, args }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(bootstrap)]
|
||||||
|
#[inline]
|
||||||
|
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
|
||||||
|
pub const fn new_v1(pieces: &'a [&'static str], args: &'a [rt::Argument<'a>]) -> Arguments<'a> {
|
||||||
|
if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
|
||||||
|
panic!("invalid args");
|
||||||
|
}
|
||||||
|
Arguments { pieces, fmt: None, args }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function is used to specify nonstandard formatting parameters.
|
||||||
|
///
|
||||||
|
/// An `rt::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::Placeholder::position` value within `fmt` must be a valid index of `args`.
|
||||||
|
/// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
|
||||||
|
#[inline]
|
||||||
|
pub fn new_v1_formatted(
|
||||||
|
pieces: &'a [&'static str],
|
||||||
|
args: &'a [rt::Argument<'a>],
|
||||||
|
fmt: &'a [rt::Placeholder],
|
||||||
|
_unsafe_arg: rt::UnsafeArg,
|
||||||
|
) -> Arguments<'a> {
|
||||||
|
Arguments { pieces, fmt: Some(fmt), args }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Estimates the length of the formatted text.
|
||||||
|
///
|
||||||
|
/// This is intended to be used for setting initial `String` capacity
|
||||||
|
/// when using `format!`. Note: this is neither the lower nor upper bound.
|
||||||
|
#[inline]
|
||||||
|
pub fn estimated_capacity(&self) -> usize {
|
||||||
|
let pieces_length: usize = self.pieces.iter().map(|x| x.len()).sum();
|
||||||
|
|
||||||
|
if self.args.is_empty() {
|
||||||
|
pieces_length
|
||||||
|
} else if !self.pieces.is_empty() && self.pieces[0].is_empty() && pieces_length < 16 {
|
||||||
|
// If the format string starts with an argument,
|
||||||
|
// don't preallocate anything, unless length
|
||||||
|
// of pieces is significant.
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
// There are some arguments, so any additional push
|
||||||
|
// will reallocate the string. To avoid that,
|
||||||
|
// we're "pre-doubling" the capacity here.
|
||||||
|
pieces_length.checked_mul(2).unwrap_or(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Arguments<'a> {
|
impl<'a> Arguments<'a> {
|
||||||
@ -1244,7 +1102,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
|
|||||||
if !piece.is_empty() {
|
if !piece.is_empty() {
|
||||||
formatter.buf.write_str(*piece)?;
|
formatter.buf.write_str(*piece)?;
|
||||||
}
|
}
|
||||||
(arg.formatter)(arg.value, &mut formatter)?;
|
arg.fmt(&mut formatter)?;
|
||||||
idx += 1;
|
idx += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1274,7 +1132,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[ArgumentV1<'_>]) -> Result {
|
unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argument<'_>]) -> Result {
|
||||||
fmt.fill = arg.fill;
|
fmt.fill = arg.fill;
|
||||||
fmt.align = arg.align;
|
fmt.align = arg.align;
|
||||||
fmt.flags = arg.flags;
|
fmt.flags = arg.flags;
|
||||||
@ -1292,10 +1150,10 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[ArgumentV1
|
|||||||
let value = unsafe { args.get_unchecked(arg.position) };
|
let value = unsafe { args.get_unchecked(arg.position) };
|
||||||
|
|
||||||
// Then actually do some printing
|
// Then actually do some printing
|
||||||
(value.formatter)(value.value, fmt)
|
value.fmt(fmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn getcount(args: &[ArgumentV1<'_>], cnt: &rt::Count) -> Option<usize> {
|
unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize> {
|
||||||
match *cnt {
|
match *cnt {
|
||||||
rt::Count::Is(n) => Some(n),
|
rt::Count::Is(n) => Some(n),
|
||||||
rt::Count::Implied => None,
|
rt::Count::Implied => None,
|
||||||
@ -1878,7 +1736,7 @@ pub fn precision(&self) -> Option<usize> {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
||||||
pub fn sign_plus(&self) -> bool {
|
pub fn sign_plus(&self) -> bool {
|
||||||
self.flags & (1 << FlagV1::SignPlus as u32) != 0
|
self.flags & (1 << rt::Flag::SignPlus as u32) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines if the `-` flag was specified.
|
/// Determines if the `-` flag was specified.
|
||||||
@ -1907,7 +1765,7 @@ pub fn sign_plus(&self) -> bool {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
||||||
pub fn sign_minus(&self) -> bool {
|
pub fn sign_minus(&self) -> bool {
|
||||||
self.flags & (1 << FlagV1::SignMinus as u32) != 0
|
self.flags & (1 << rt::Flag::SignMinus as u32) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines if the `#` flag was specified.
|
/// Determines if the `#` flag was specified.
|
||||||
@ -1935,7 +1793,7 @@ pub fn sign_minus(&self) -> bool {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
||||||
pub fn alternate(&self) -> bool {
|
pub fn alternate(&self) -> bool {
|
||||||
self.flags & (1 << FlagV1::Alternate as u32) != 0
|
self.flags & (1 << rt::Flag::Alternate as u32) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines if the `0` flag was specified.
|
/// Determines if the `0` flag was specified.
|
||||||
@ -1961,17 +1819,17 @@ pub fn alternate(&self) -> bool {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
||||||
pub fn sign_aware_zero_pad(&self) -> bool {
|
pub fn sign_aware_zero_pad(&self) -> bool {
|
||||||
self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0
|
self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Decide what public API we want for these two flags.
|
// FIXME: Decide what public API we want for these two flags.
|
||||||
// https://github.com/rust-lang/rust/issues/48584
|
// https://github.com/rust-lang/rust/issues/48584
|
||||||
fn debug_lower_hex(&self) -> bool {
|
fn debug_lower_hex(&self) -> bool {
|
||||||
self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0
|
self.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_upper_hex(&self) -> bool {
|
fn debug_upper_hex(&self) -> bool {
|
||||||
self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0
|
self.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a [`DebugStruct`] builder designed to assist with creation of
|
/// Creates a [`DebugStruct`] builder designed to assist with creation of
|
||||||
@ -2531,13 +2389,13 @@ pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Resul
|
|||||||
// or not to zero extend, and then unconditionally set it to get the
|
// or not to zero extend, and then unconditionally set it to get the
|
||||||
// prefix.
|
// prefix.
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
|
f.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32);
|
||||||
|
|
||||||
if f.width.is_none() {
|
if f.width.is_none() {
|
||||||
f.width = Some((usize::BITS / 4) as usize + 2);
|
f.width = Some((usize::BITS / 4) as usize + 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.flags |= 1 << (FlagV1::Alternate as u32);
|
f.flags |= 1 << (rt::Flag::Alternate as u32);
|
||||||
|
|
||||||
let ret = LowerHex::fmt(&ptr_addr, f);
|
let ret = LowerHex::fmt(&ptr_addr, f);
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
//! These are the lang items used by format_args!().
|
//! These are the lang items used by format_args!().
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[lang = "format_placeholder"]
|
#[lang = "format_placeholder"]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Placeholder {
|
pub struct Placeholder {
|
||||||
@ -28,21 +30,17 @@ pub const fn new(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Possible alignments that can be requested as part of a formatting directive.
|
|
||||||
#[lang = "format_alignment"]
|
#[lang = "format_alignment"]
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum Alignment {
|
pub enum Alignment {
|
||||||
/// Indication that contents should be left-aligned.
|
|
||||||
Left,
|
Left,
|
||||||
/// Indication that contents should be right-aligned.
|
|
||||||
Right,
|
Right,
|
||||||
/// Indication that contents should be center-aligned.
|
|
||||||
Center,
|
Center,
|
||||||
/// No alignment was requested.
|
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers.
|
/// Used by [width](https://doc.rust-lang.org/std/fmt/#width)
|
||||||
|
/// and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers.
|
||||||
#[lang = "format_count"]
|
#[lang = "format_count"]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Count {
|
pub enum Count {
|
||||||
@ -53,3 +51,147 @@ pub enum Count {
|
|||||||
/// Not specified
|
/// Not specified
|
||||||
Implied,
|
Implied,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This needs to match the order of flags in compiler/rustc_ast_lowering/src/format.rs.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub(super) enum Flag {
|
||||||
|
SignPlus,
|
||||||
|
SignMinus,
|
||||||
|
Alternate,
|
||||||
|
SignAwareZeroPad,
|
||||||
|
DebugLowerHex,
|
||||||
|
DebugUpperHex,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This struct represents the generic "argument" which is taken by format_args!().
|
||||||
|
/// It contains a function to format the given value. At compile time it is ensured that the
|
||||||
|
/// function and the value have the correct types, and then this struct is used to canonicalize
|
||||||
|
/// arguments to one type.
|
||||||
|
///
|
||||||
|
/// Argument is essentially an optimized partially applied formatting function,
|
||||||
|
/// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`.
|
||||||
|
#[lang = "format_argument"]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Argument<'a> {
|
||||||
|
value: &'a Opaque,
|
||||||
|
formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustc_diagnostic_item = "ArgumentMethods"]
|
||||||
|
impl<'a> Argument<'a> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'b> {
|
||||||
|
// SAFETY: `mem::transmute(x)` is safe because
|
||||||
|
// 1. `&'b T` keeps the lifetime it originated with `'b`
|
||||||
|
// (so as to not have an unbounded lifetime)
|
||||||
|
// 2. `&'b T` and `&'b Opaque` have the same memory layout
|
||||||
|
// (when `T` is `Sized`, as it is here)
|
||||||
|
// `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
|
||||||
|
// and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI
|
||||||
|
// (as long as `T` is `Sized`)
|
||||||
|
unsafe { Argument { formatter: mem::transmute(f), value: mem::transmute(x) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'_> {
|
||||||
|
Self::new(x, Display::fmt)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'_> {
|
||||||
|
Self::new(x, Debug::fmt)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'_> {
|
||||||
|
Self::new(x, Octal::fmt)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'_> {
|
||||||
|
Self::new(x, LowerHex::fmt)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'_> {
|
||||||
|
Self::new(x, UpperHex::fmt)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'_> {
|
||||||
|
Self::new(x, Pointer::fmt)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'_> {
|
||||||
|
Self::new(x, Binary::fmt)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'_> {
|
||||||
|
Self::new(x, LowerExp::fmt)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'_> {
|
||||||
|
Self::new(x, UpperExp::fmt)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn from_usize(x: &usize) -> Argument<'_> {
|
||||||
|
Self::new(x, USIZE_MARKER)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(super) fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||||
|
(self.formatter)(self.value, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub(super) fn as_usize(&self) -> Option<usize> {
|
||||||
|
// We are type punning a bit here: USIZE_MARKER only takes an &usize but
|
||||||
|
// formatter takes an &Opaque. Rust understandably doesn't think we should compare
|
||||||
|
// the function pointers if they don't have the same signature, so we cast to
|
||||||
|
// usizes to tell it that we just want to compare addresses.
|
||||||
|
if self.formatter as usize == USIZE_MARKER as usize {
|
||||||
|
// SAFETY: The `formatter` field is only set to USIZE_MARKER if
|
||||||
|
// the value is a usize, so this is safe
|
||||||
|
Some(unsafe { *(self.value as *const _ as *const usize) })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
#[lang = "format_unsafe_arg"]
|
||||||
|
pub struct UnsafeArg {
|
||||||
|
_private: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnsafeArg {
|
||||||
|
/// See documentation where `UnsafeArg` is required to know when it is safe to
|
||||||
|
/// create and use `UnsafeArg`.
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn new() -> Self {
|
||||||
|
Self { _private: () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
type Opaque;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This guarantees a single stable value for the function pointer associated with
|
||||||
|
// indices/counts in the formatting infrastructure.
|
||||||
|
//
|
||||||
|
// Note that a function defined as such would not be correct as functions are
|
||||||
|
// always tagged unnamed_addr with the current lowering to LLVM IR, so their
|
||||||
|
// address is not considered important to LLVM and as such the as_usize cast
|
||||||
|
// could have been miscompiled. In practice, we never call as_usize on non-usize
|
||||||
|
// containing data (as a matter of static generation of the formatting
|
||||||
|
// arguments), so this is merely an additional check.
|
||||||
|
//
|
||||||
|
// We primarily want to ensure that the function pointer at `USIZE_MARKER` has
|
||||||
|
// an address corresponding *only* to functions that also take `&usize` as their
|
||||||
|
// first argument. The read_volatile here ensures that we can safely ready out a
|
||||||
|
// usize from the passed reference and that this address does not point at a
|
||||||
|
// non-usize taking function.
|
||||||
|
static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| {
|
||||||
|
// SAFETY: ptr is a reference
|
||||||
|
let _v: usize = unsafe { crate::ptr::read_volatile(ptr) };
|
||||||
|
loop {}
|
||||||
|
};
|
||||||
|
@ -12,57 +12,59 @@ stack backtrace:
|
|||||||
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
||||||
4: <std::sys_common::backtrace::_print::DisplayBacktrace as std::fmt::Display>::fmt
|
4: <std::sys_common::backtrace::_print::DisplayBacktrace as std::fmt::Display>::fmt
|
||||||
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
||||||
5: std::fmt::write
|
5: core::fmt::rt::Argument::fmt
|
||||||
|
at RUSTLIB/core/src/fmt/rt.rs:LL:CC
|
||||||
|
6: std::fmt::write
|
||||||
at RUSTLIB/core/src/fmt/mod.rs:LL:CC
|
at RUSTLIB/core/src/fmt/mod.rs:LL:CC
|
||||||
6: <std::sys::PLATFORM::stdio::Stderr as std::io::Write>::write_fmt
|
7: <std::sys::PLATFORM::stdio::Stderr as std::io::Write>::write_fmt
|
||||||
at RUSTLIB/std/src/io/mod.rs:LL:CC
|
at RUSTLIB/std/src/io/mod.rs:LL:CC
|
||||||
7: std::sys_common::backtrace::_print
|
8: std::sys_common::backtrace::_print
|
||||||
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
||||||
8: std::sys_common::backtrace::print
|
9: std::sys_common::backtrace::print
|
||||||
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
||||||
9: std::panicking::default_hook::{closure#1}
|
10: std::panicking::default_hook::{closure#1}
|
||||||
at RUSTLIB/std/src/panicking.rs:LL:CC
|
at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
10: std::panicking::default_hook
|
11: std::panicking::default_hook
|
||||||
at RUSTLIB/std/src/panicking.rs:LL:CC
|
at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
11: std::panicking::rust_panic_with_hook
|
12: std::panicking::rust_panic_with_hook
|
||||||
at RUSTLIB/std/src/panicking.rs:LL:CC
|
at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
12: std::rt::begin_panic::{closure#0}
|
13: std::rt::begin_panic::{closure#0}
|
||||||
at RUSTLIB/std/src/panicking.rs:LL:CC
|
at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
13: std::sys_common::backtrace::__rust_end_short_backtrace
|
14: std::sys_common::backtrace::__rust_end_short_backtrace
|
||||||
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
||||||
14: std::rt::begin_panic
|
15: std::rt::begin_panic
|
||||||
at RUSTLIB/std/src/panicking.rs:LL:CC
|
at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
15: <Foo as std::ops::Drop>::drop
|
16: <Foo as std::ops::Drop>::drop
|
||||||
at $DIR/double_panic.rs:LL:CC
|
at $DIR/double_panic.rs:LL:CC
|
||||||
16: std::ptr::drop_in_place - shim(Some(Foo))
|
17: std::ptr::drop_in_place - shim(Some(Foo))
|
||||||
at RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
at RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||||
17: main
|
18: main
|
||||||
at $DIR/double_panic.rs:LL:CC
|
at $DIR/double_panic.rs:LL:CC
|
||||||
18: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
|
19: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
|
||||||
at RUSTLIB/core/src/ops/function.rs:LL:CC
|
at RUSTLIB/core/src/ops/function.rs:LL:CC
|
||||||
19: std::sys_common::backtrace::__rust_begin_short_backtrace
|
20: std::sys_common::backtrace::__rust_begin_short_backtrace
|
||||||
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
|
||||||
20: std::rt::lang_start::{closure#0}
|
21: std::rt::lang_start::{closure#0}
|
||||||
at RUSTLIB/std/src/rt.rs:LL:CC
|
at RUSTLIB/std/src/rt.rs:LL:CC
|
||||||
21: std::ops::function::impls::call_once
|
22: std::ops::function::impls::call_once
|
||||||
at RUSTLIB/core/src/ops/function.rs:LL:CC
|
at RUSTLIB/core/src/ops/function.rs:LL:CC
|
||||||
22: std::panicking::r#try::do_call
|
23: std::panicking::r#try::do_call
|
||||||
at RUSTLIB/std/src/panicking.rs:LL:CC
|
at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
23: std::panicking::r#try
|
24: std::panicking::r#try
|
||||||
at RUSTLIB/std/src/panicking.rs:LL:CC
|
at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
24: std::panic::catch_unwind
|
25: std::panic::catch_unwind
|
||||||
at RUSTLIB/std/src/panic.rs:LL:CC
|
at RUSTLIB/std/src/panic.rs:LL:CC
|
||||||
25: std::rt::lang_start_internal::{closure#2}
|
26: std::rt::lang_start_internal::{closure#2}
|
||||||
at RUSTLIB/std/src/rt.rs:LL:CC
|
at RUSTLIB/std/src/rt.rs:LL:CC
|
||||||
26: std::panicking::r#try::do_call
|
27: std::panicking::r#try::do_call
|
||||||
at RUSTLIB/std/src/panicking.rs:LL:CC
|
at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
27: std::panicking::r#try
|
28: std::panicking::r#try
|
||||||
at RUSTLIB/std/src/panicking.rs:LL:CC
|
at RUSTLIB/std/src/panicking.rs:LL:CC
|
||||||
28: std::panic::catch_unwind
|
29: std::panic::catch_unwind
|
||||||
at RUSTLIB/std/src/panic.rs:LL:CC
|
at RUSTLIB/std/src/panic.rs:LL:CC
|
||||||
29: std::rt::lang_start_internal
|
30: std::rt::lang_start_internal
|
||||||
at RUSTLIB/std/src/rt.rs:LL:CC
|
at RUSTLIB/std/src/rt.rs:LL:CC
|
||||||
30: std::rt::lang_start
|
31: std::rt::lang_start
|
||||||
at RUSTLIB/std/src/rt.rs:LL:CC
|
at RUSTLIB/std/src/rt.rs:LL:CC
|
||||||
thread panicked while panicking. aborting.
|
thread panicked while panicking. aborting.
|
||||||
error: abnormal termination: the program aborted execution
|
error: abnormal termination: the program aborted execution
|
||||||
|
@ -201,7 +201,7 @@ macro_rules! format_args {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
$crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(arg1(a, b, c)), $crate::fmt::Display::fmt), $crate::fmt::ArgumentV1::new(&(arg2), $crate::fmt::Display::fmt), ]);
|
$crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::Argument::new(&(arg1(a, b, c)), $crate::fmt::Display::fmt), $crate::fmt::Argument::new(&(arg2), $crate::fmt::Display::fmt), ]);
|
||||||
}
|
}
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
@ -229,7 +229,7 @@ macro_rules! format_args {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
$crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(a::<A, B>()), $crate::fmt::Display::fmt), $crate::fmt::ArgumentV1::new(&(b), $crate::fmt::Display::fmt), ]);
|
$crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::Argument::new(&(a::<A, B>()), $crate::fmt::Display::fmt), $crate::fmt::Argument::new(&(b), $crate::fmt::Display::fmt), ]);
|
||||||
}
|
}
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
@ -260,7 +260,7 @@ macro_rules! format_args {
|
|||||||
fn main() {
|
fn main() {
|
||||||
let _ =
|
let _ =
|
||||||
/* parse error: expected field name or number */
|
/* parse error: expected field name or number */
|
||||||
$crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(a.), $crate::fmt::Display::fmt), ]);
|
$crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::Argument::new(&(a.), $crate::fmt::Display::fmt), ]);
|
||||||
}
|
}
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
@ -241,8 +241,8 @@ fn format_args_expand(
|
|||||||
// We expand `format_args!("", a1, a2)` to
|
// We expand `format_args!("", a1, a2)` to
|
||||||
// ```
|
// ```
|
||||||
// $crate::fmt::Arguments::new_v1(&[], &[
|
// $crate::fmt::Arguments::new_v1(&[], &[
|
||||||
// $crate::fmt::ArgumentV1::new(&arg1,$crate::fmt::Display::fmt),
|
// $crate::fmt::Argument::new(&arg1,$crate::fmt::Display::fmt),
|
||||||
// $crate::fmt::ArgumentV1::new(&arg2,$crate::fmt::Display::fmt),
|
// $crate::fmt::Argument::new(&arg2,$crate::fmt::Display::fmt),
|
||||||
// ])
|
// ])
|
||||||
// ```,
|
// ```,
|
||||||
// which is still not really correct, but close enough for now
|
// which is still not really correct, but close enough for now
|
||||||
@ -267,7 +267,7 @@ fn format_args_expand(
|
|||||||
}
|
}
|
||||||
let _format_string = args.remove(0);
|
let _format_string = args.remove(0);
|
||||||
let arg_tts = args.into_iter().flat_map(|arg| {
|
let arg_tts = args.into_iter().flat_map(|arg| {
|
||||||
quote! { #DOLLAR_CRATE::fmt::ArgumentV1::new(&(#arg), #DOLLAR_CRATE::fmt::Display::fmt), }
|
quote! { #DOLLAR_CRATE::fmt::Argument::new(&(#arg), #DOLLAR_CRATE::fmt::Display::fmt), }
|
||||||
}.token_trees);
|
}.token_trees);
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
#DOLLAR_CRATE::fmt::Arguments::new_v1(&[], &[##arg_tts])
|
#DOLLAR_CRATE::fmt::Arguments::new_v1(&[], &[##arg_tts])
|
||||||
|
@ -15,14 +15,14 @@
|
|||||||
let mut _13: &[&str; 3]; // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
|
let mut _13: &[&str; 3]; // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
|
||||||
let _14: &[&str; 3]; // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
|
let _14: &[&str; 3]; // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
|
||||||
let _15: [&str; 3]; // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
|
let _15: [&str; 3]; // in scope 0 at $DIR/lifetimes.rs:+10:19: +10:28
|
||||||
let mut _16: &[core::fmt::ArgumentV1<'_>]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
|
let mut _16: &[core::fmt::rt::Argument<'_>]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||||
let mut _17: &[core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
|
let mut _17: &[core::fmt::rt::Argument<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||||
let _18: &[core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
|
let _18: &[core::fmt::rt::Argument<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||||
let _19: [core::fmt::ArgumentV1<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
|
let _19: [core::fmt::rt::Argument<'_>; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||||
let mut _20: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
|
let mut _20: core::fmt::rt::Argument<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||||
let mut _21: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
|
let mut _21: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||||
let _22: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
|
let _22: &std::boxed::Box<dyn std::fmt::Display>; // in scope 0 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||||
let mut _23: core::fmt::ArgumentV1<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
|
let mut _23: core::fmt::rt::Argument<'_>; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||||
let mut _24: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
|
let mut _24: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||||
let _25: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
|
let _25: &u32; // in scope 0 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||||
let mut _27: bool; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
|
let mut _27: bool; // in scope 0 at $DIR/lifetimes.rs:+12:1: +12:2
|
||||||
@ -113,11 +113,11 @@
|
|||||||
StorageLive(_22); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
StorageLive(_22); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||||
_22 = &_8; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
_22 = &_8; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||||
_21 = &(*_22); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
_21 = &(*_22); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||||
_20 = core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _21) -> [return: bb3, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
_20 = core::fmt::rt::Argument::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _21) -> [return: bb3, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/lifetimes.rs:27:20: 27:23
|
// + span: $DIR/lifetimes.rs:27:20: 27:23
|
||||||
// + user_ty: UserType(4)
|
// + user_ty: UserType(4)
|
||||||
// + literal: Const { ty: for<'b> fn(&'b Box<dyn std::fmt::Display>) -> core::fmt::ArgumentV1<'b> {core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>}, val: Value(<ZST>) }
|
// + literal: Const { ty: for<'b> fn(&'b Box<dyn std::fmt::Display>) -> core::fmt::rt::Argument<'b> {core::fmt::rt::Argument::<'_>::new_display::<Box<dyn std::fmt::Display>>}, val: Value(<ZST>) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
@ -127,11 +127,11 @@
|
|||||||
StorageLive(_25); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
StorageLive(_25); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||||
_25 = &_6; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
_25 = &_6; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||||
_24 = &(*_25); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
_24 = &(*_25); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||||
_23 = core::fmt::ArgumentV1::<'_>::new_display::<u32>(move _24) -> [return: bb4, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
_23 = core::fmt::rt::Argument::<'_>::new_display::<u32>(move _24) -> [return: bb4, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/lifetimes.rs:27:24: 27:27
|
// + span: $DIR/lifetimes.rs:27:24: 27:27
|
||||||
// + user_ty: UserType(5)
|
// + user_ty: UserType(5)
|
||||||
// + literal: Const { ty: for<'b> fn(&'b u32) -> core::fmt::ArgumentV1<'b> {core::fmt::ArgumentV1::<'_>::new_display::<u32>}, val: Value(<ZST>) }
|
// + literal: Const { ty: for<'b> fn(&'b u32) -> core::fmt::rt::Argument<'b> {core::fmt::rt::Argument::<'_>::new_display::<u32>}, val: Value(<ZST>) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
@ -141,13 +141,13 @@
|
|||||||
StorageDead(_20); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
StorageDead(_20); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||||
_18 = &_19; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
_18 = &_19; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||||
_17 = &(*_18); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
_17 = &(*_18); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||||
_16 = move _17 as &[core::fmt::ArgumentV1<'_>] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
_16 = move _17 as &[core::fmt::rt::Argument<'_>] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||||
StorageDead(_17); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
StorageDead(_17); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||||
_11 = Arguments::<'_>::new_v1(move _12, move _16) -> [return: bb5, unwind unreachable]; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
_11 = Arguments::<'_>::new_v1(move _12, move _16) -> [return: bb5, unwind unreachable]; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $SRC_DIR/std/src/macros.rs:LL:COL
|
// + span: $SRC_DIR/std/src/macros.rs:LL:COL
|
||||||
// + user_ty: UserType(3)
|
// + user_ty: UserType(3)
|
||||||
// + literal: Const { ty: fn(&[&'static str], &[core::fmt::ArgumentV1<'_>]) -> Arguments<'_> {Arguments::<'_>::new_v1}, val: Value(<ZST>) }
|
// + literal: Const { ty: fn(&[&'static str], &[core::fmt::rt::Argument<'_>]) -> Arguments<'_> {Arguments::<'_>::new_v1}, val: Value(<ZST>) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
|
@ -307,7 +307,7 @@ LL | println!("{} {:.*} {}", 1, 3.2, 4);
|
|||||||
= note: expected reference `&usize`
|
= note: expected reference `&usize`
|
||||||
found reference `&{float}`
|
found reference `&{float}`
|
||||||
note: associated function defined here
|
note: associated function defined here
|
||||||
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
|
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
|
||||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
@ -321,7 +321,7 @@ LL | println!("{} {:07$.*} {}", 1, 3.2, 4);
|
|||||||
= note: expected reference `&usize`
|
= note: expected reference `&usize`
|
||||||
found reference `&{float}`
|
found reference `&{float}`
|
||||||
note: associated function defined here
|
note: associated function defined here
|
||||||
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
|
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
|
||||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 38 previous errors
|
error: aborting due to 38 previous errors
|
||||||
|
@ -17,9 +17,9 @@ LL | format!("{:X}", "3");
|
|||||||
NonZeroIsize
|
NonZeroIsize
|
||||||
and 21 others
|
and 21 others
|
||||||
= note: required for `&str` to implement `UpperHex`
|
= note: required for `&str` to implement `UpperHex`
|
||||||
note: required by a bound in `core::fmt::ArgumentV1::<'a>::new_upper_hex`
|
note: required by a bound in `core::fmt::rt::Argument::<'a>::new_upper_hex`
|
||||||
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
|
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
|
||||||
= note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `arg_new` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely
|
error[E0277]: `core::fmt::rt::Opaque` cannot be shared between threads safely
|
||||||
--> $DIR/send-sync.rs:8:10
|
--> $DIR/send-sync.rs:8:10
|
||||||
|
|
|
|
||||||
LL | send(format_args!("{:?}", c));
|
LL | send(format_args!("{:?}", c));
|
||||||
| ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::Opaque` cannot be shared between threads safely
|
| ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::rt::Opaque` cannot be shared between threads safely
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: within `[core::fmt::ArgumentV1<'_>]`, the trait `Sync` is not implemented for `core::fmt::Opaque`
|
= help: within `[core::fmt::rt::Argument<'_>]`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`
|
||||||
= note: required because it appears within the type `&core::fmt::Opaque`
|
= note: required because it appears within the type `&core::fmt::rt::Opaque`
|
||||||
= note: required because it appears within the type `ArgumentV1<'_>`
|
= note: required because it appears within the type `Argument<'_>`
|
||||||
= note: required because it appears within the type `[ArgumentV1<'_>]`
|
= note: required because it appears within the type `[Argument<'_>]`
|
||||||
= note: required for `&[core::fmt::ArgumentV1<'_>]` to implement `Send`
|
= note: required for `&[core::fmt::rt::Argument<'_>]` to implement `Send`
|
||||||
= note: required because it appears within the type `Arguments<'_>`
|
= note: required because it appears within the type `Arguments<'_>`
|
||||||
note: required by a bound in `send`
|
note: required by a bound in `send`
|
||||||
--> $DIR/send-sync.rs:1:12
|
--> $DIR/send-sync.rs:1:12
|
||||||
@ -18,19 +18,19 @@ note: required by a bound in `send`
|
|||||||
LL | fn send<T: Send>(_: T) {}
|
LL | fn send<T: Send>(_: T) {}
|
||||||
| ^^^^ required by this bound in `send`
|
| ^^^^ required by this bound in `send`
|
||||||
|
|
||||||
error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely
|
error[E0277]: `core::fmt::rt::Opaque` cannot be shared between threads safely
|
||||||
--> $DIR/send-sync.rs:9:10
|
--> $DIR/send-sync.rs:9:10
|
||||||
|
|
|
|
||||||
LL | sync(format_args!("{:?}", c));
|
LL | sync(format_args!("{:?}", c));
|
||||||
| ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::Opaque` cannot be shared between threads safely
|
| ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::rt::Opaque` cannot be shared between threads safely
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::Opaque`
|
= help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`
|
||||||
= note: required because it appears within the type `&core::fmt::Opaque`
|
= note: required because it appears within the type `&core::fmt::rt::Opaque`
|
||||||
= note: required because it appears within the type `ArgumentV1<'_>`
|
= note: required because it appears within the type `Argument<'_>`
|
||||||
= note: required because it appears within the type `[ArgumentV1<'_>]`
|
= note: required because it appears within the type `[Argument<'_>]`
|
||||||
= note: required because it appears within the type `&[ArgumentV1<'_>]`
|
= note: required because it appears within the type `&[Argument<'_>]`
|
||||||
= note: required because it appears within the type `Arguments<'_>`
|
= note: required because it appears within the type `Arguments<'_>`
|
||||||
note: required by a bound in `sync`
|
note: required by a bound in `sync`
|
||||||
--> $DIR/send-sync.rs:2:12
|
--> $DIR/send-sync.rs:2:12
|
||||||
|
Loading…
Reference in New Issue
Block a user