Skip to content

Commit 0a28977

Browse files
committed
Restructure std::fmt::rt a bit.
This moves more of the internal/lang items into the private rt module.
1 parent 5cf3cbf commit 0a28977

File tree

3 files changed

+201
-201
lines changed

3 files changed

+201
-201
lines changed

compiler/rustc_ast_lowering/src/format.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ fn make_format_spec<'hir>(
327327
None => sym::Unknown,
328328
},
329329
);
330-
// This needs to match `Flag` in library/core/src/fmt/mod.rs.
330+
// This needs to match `Flag` in library/core/src/fmt/rt.rs.
331331
let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
332332
| ((sign == Some(FormatSign::Minus)) as u32) << 1
333333
| (alternate as u32) << 2

library/core/src/fmt/mod.rs

Lines changed: 52 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -251,145 +251,48 @@ impl<'a> Formatter<'a> {
251251
}
252252
}
253253

254-
// NB. Argument is essentially an optimized partially applied formatting function,
255-
// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`.
256-
257-
extern "C" {
258-
type Opaque;
259-
}
260-
261-
/// This struct represents the generic "argument" which is taken by the Xprintf
262-
/// family of functions. It contains a function to format the given value. At
263-
/// compile time it is ensured that the function and the value have the correct
264-
/// types, and then this struct is used to canonicalize arguments to one type.
265-
#[lang = "format_argument"]
254+
/// This structure represents a safely precompiled version of a format string
255+
/// and its arguments. This cannot be generated at runtime because it cannot
256+
/// safely be done, so no constructors are given and the fields are private
257+
/// to prevent modification.
258+
///
259+
/// The [`format_args!`] macro will safely create an instance of this structure.
260+
/// The macro validates the format string at compile-time so usage of the
261+
/// [`write()`] and [`format()`] functions can be safely performed.
262+
///
263+
/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug`
264+
/// and `Display` contexts as seen below. The example also shows that `Debug`
265+
/// and `Display` format to the same thing: the interpolated format string
266+
/// in `format_args!`.
267+
///
268+
/// ```rust
269+
/// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
270+
/// let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
271+
/// assert_eq!("1 foo 2", display);
272+
/// assert_eq!(display, debug);
273+
/// ```
274+
///
275+
/// [`format()`]: ../../std/fmt/fn.format.html
276+
#[lang = "format_arguments"]
277+
#[stable(feature = "rust1", since = "1.0.0")]
266278
#[derive(Copy, Clone)]
267-
#[allow(missing_debug_implementations)]
268-
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
269-
#[doc(hidden)]
270-
pub struct Argument<'a> {
271-
value: &'a Opaque,
272-
formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,
273-
}
274-
275-
/// This struct represents the unsafety of constructing an `Arguments`.
276-
/// It exists, rather than an unsafe function, in order to simplify the expansion
277-
/// of `format_args!(..)` and reduce the scope of the `unsafe` block.
278-
#[lang = "format_unsafe_arg"]
279-
#[allow(missing_debug_implementations)]
280-
#[doc(hidden)]
281-
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
282-
pub struct UnsafeArg {
283-
_private: (),
284-
}
285-
286-
impl UnsafeArg {
287-
/// See documentation where `UnsafeArg` is required to know when it is safe to
288-
/// create and use `UnsafeArg`.
289-
#[doc(hidden)]
290-
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
291-
#[inline(always)]
292-
pub unsafe fn new() -> Self {
293-
Self { _private: () }
294-
}
295-
}
296-
297-
// This guarantees a single stable value for the function pointer associated with
298-
// indices/counts in the formatting infrastructure.
299-
//
300-
// Note that a function defined as such would not be correct as functions are
301-
// always tagged unnamed_addr with the current lowering to LLVM IR, so their
302-
// address is not considered important to LLVM and as such the as_usize cast
303-
// could have been miscompiled. In practice, we never call as_usize on non-usize
304-
// containing data (as a matter of static generation of the formatting
305-
// arguments), so this is merely an additional check.
306-
//
307-
// We primarily want to ensure that the function pointer at `USIZE_MARKER` has
308-
// an address corresponding *only* to functions that also take `&usize` as their
309-
// first argument. The read_volatile here ensures that we can safely ready out a
310-
// usize from the passed reference and that this address does not point at a
311-
// non-usize taking function.
312-
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
313-
static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| {
314-
// SAFETY: ptr is a reference
315-
let _v: usize = unsafe { crate::ptr::read_volatile(ptr) };
316-
loop {}
317-
};
318-
319-
macro_rules! arg_new {
320-
($f: ident, $t: ident) => {
321-
#[doc(hidden)]
322-
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
323-
#[inline]
324-
pub fn $f<'b, T: $t>(x: &'b T) -> Argument<'_> {
325-
Self::new(x, $t::fmt)
326-
}
327-
};
328-
}
329-
330-
#[rustc_diagnostic_item = "ArgumentMethods"]
331-
impl<'a> Argument<'a> {
332-
#[doc(hidden)]
333-
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
334-
#[inline]
335-
pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'b> {
336-
// SAFETY: `mem::transmute(x)` is safe because
337-
// 1. `&'b T` keeps the lifetime it originated with `'b`
338-
// (so as to not have an unbounded lifetime)
339-
// 2. `&'b T` and `&'b Opaque` have the same memory layout
340-
// (when `T` is `Sized`, as it is here)
341-
// `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
342-
// and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI
343-
// (as long as `T` is `Sized`)
344-
unsafe { Argument { formatter: mem::transmute(f), value: mem::transmute(x) } }
345-
}
346-
347-
arg_new!(new_display, Display);
348-
arg_new!(new_debug, Debug);
349-
arg_new!(new_octal, Octal);
350-
arg_new!(new_lower_hex, LowerHex);
351-
arg_new!(new_upper_hex, UpperHex);
352-
arg_new!(new_pointer, Pointer);
353-
arg_new!(new_binary, Binary);
354-
arg_new!(new_lower_exp, LowerExp);
355-
arg_new!(new_upper_exp, UpperExp);
279+
pub struct Arguments<'a> {
280+
// Format string pieces to print.
281+
pieces: &'a [&'static str],
356282

357-
#[doc(hidden)]
358-
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
359-
pub fn from_usize(x: &usize) -> Argument<'_> {
360-
Argument::new(x, USIZE_MARKER)
361-
}
362-
363-
fn as_usize(&self) -> Option<usize> {
364-
// We are type punning a bit here: USIZE_MARKER only takes an &usize but
365-
// formatter takes an &Opaque. Rust understandably doesn't think we should compare
366-
// the function pointers if they don't have the same signature, so we cast to
367-
// usizes to tell it that we just want to compare addresses.
368-
if self.formatter as usize == USIZE_MARKER as usize {
369-
// SAFETY: The `formatter` field is only set to USIZE_MARKER if
370-
// the value is a usize, so this is safe
371-
Some(unsafe { *(self.value as *const _ as *const usize) })
372-
} else {
373-
None
374-
}
375-
}
376-
}
283+
// Placeholder specs, or `None` if all specs are default (as in "{}{}").
284+
fmt: Option<&'a [rt::Placeholder]>,
377285

378-
// flags available in the v1 format of format_args
379-
#[derive(Copy, Clone)]
380-
enum Flag {
381-
SignPlus,
382-
SignMinus,
383-
Alternate,
384-
SignAwareZeroPad,
385-
DebugLowerHex,
386-
DebugUpperHex,
286+
// Dynamic arguments for interpolation, to be interleaved with string
287+
// pieces. (Every argument is preceded by a string piece.)
288+
args: &'a [rt::Argument<'a>],
387289
}
388290

291+
/// Used by the format_args!() macro to create a fmt::Arguments object.
292+
#[doc(hidden)]
293+
#[unstable(feature = "fmt_internals", issue = "none")]
389294
impl<'a> Arguments<'a> {
390-
#[doc(hidden)]
391295
#[inline]
392-
#[unstable(feature = "fmt_internals", issue = "none")]
393296
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
394297
pub const fn new_const(pieces: &'a [&'static str]) -> Self {
395298
if pieces.len() > 1 {
@@ -401,22 +304,18 @@ impl<'a> Arguments<'a> {
401304
/// When using the format_args!() macro, this function is used to generate the
402305
/// Arguments structure.
403306
#[cfg(not(bootstrap))]
404-
#[doc(hidden)]
405307
#[inline]
406-
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
407-
pub fn new_v1(pieces: &'a [&'static str], args: &'a [Argument<'a>]) -> Arguments<'a> {
308+
pub fn new_v1(pieces: &'a [&'static str], args: &'a [rt::Argument<'a>]) -> Arguments<'a> {
408309
if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
409310
panic!("invalid args");
410311
}
411312
Arguments { pieces, fmt: None, args }
412313
}
413314

414315
#[cfg(bootstrap)]
415-
#[doc(hidden)]
416316
#[inline]
417-
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
418317
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
419-
pub const fn new_v1(pieces: &'a [&'static str], args: &'a [Argument<'a>]) -> Arguments<'a> {
318+
pub const fn new_v1(pieces: &'a [&'static str], args: &'a [rt::Argument<'a>]) -> Arguments<'a> {
420319
if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
421320
panic!("invalid args");
422321
}
@@ -425,19 +324,17 @@ impl<'a> Arguments<'a> {
425324

426325
/// This function is used to specify nonstandard formatting parameters.
427326
///
428-
/// An `UnsafeArg` is required because the following invariants must be held
327+
/// An `rt::UnsafeArg` is required because the following invariants must be held
429328
/// in order for this function to be safe:
430329
/// 1. The `pieces` slice must be at least as long as `fmt`.
431330
/// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`.
432331
/// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
433-
#[doc(hidden)]
434332
#[inline]
435-
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
436333
pub fn new_v1_formatted(
437334
pieces: &'a [&'static str],
438-
args: &'a [Argument<'a>],
335+
args: &'a [rt::Argument<'a>],
439336
fmt: &'a [rt::Placeholder],
440-
_unsafe_arg: UnsafeArg,
337+
_unsafe_arg: rt::UnsafeArg,
441338
) -> Arguments<'a> {
442339
Arguments { pieces, fmt: Some(fmt), args }
443340
}
@@ -446,9 +343,7 @@ impl<'a> Arguments<'a> {
446343
///
447344
/// This is intended to be used for setting initial `String` capacity
448345
/// when using `format!`. Note: this is neither the lower nor upper bound.
449-
#[doc(hidden)]
450346
#[inline]
451-
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
452347
pub fn estimated_capacity(&self) -> usize {
453348
let pieces_length: usize = self.pieces.iter().map(|x| x.len()).sum();
454349

@@ -468,43 +363,6 @@ impl<'a> Arguments<'a> {
468363
}
469364
}
470365

471-
/// This structure represents a safely precompiled version of a format string
472-
/// and its arguments. This cannot be generated at runtime because it cannot
473-
/// safely be done, so no constructors are given and the fields are private
474-
/// to prevent modification.
475-
///
476-
/// The [`format_args!`] macro will safely create an instance of this structure.
477-
/// The macro validates the format string at compile-time so usage of the
478-
/// [`write()`] and [`format()`] functions can be safely performed.
479-
///
480-
/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug`
481-
/// and `Display` contexts as seen below. The example also shows that `Debug`
482-
/// and `Display` format to the same thing: the interpolated format string
483-
/// in `format_args!`.
484-
///
485-
/// ```rust
486-
/// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
487-
/// let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
488-
/// assert_eq!("1 foo 2", display);
489-
/// assert_eq!(display, debug);
490-
/// ```
491-
///
492-
/// [`format()`]: ../../std/fmt/fn.format.html
493-
#[lang = "format_arguments"]
494-
#[stable(feature = "rust1", since = "1.0.0")]
495-
#[derive(Copy, Clone)]
496-
pub struct Arguments<'a> {
497-
// Format string pieces to print.
498-
pieces: &'a [&'static str],
499-
500-
// Placeholder specs, or `None` if all specs are default (as in "{}{}").
501-
fmt: Option<&'a [rt::Placeholder]>,
502-
503-
// Dynamic arguments for interpolation, to be interleaved with string
504-
// pieces. (Every argument is preceded by a string piece.)
505-
args: &'a [Argument<'a>],
506-
}
507-
508366
impl<'a> Arguments<'a> {
509367
/// Get the formatted string, if it has no arguments to be formatted at runtime.
510368
///
@@ -1244,7 +1102,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
12441102
if !piece.is_empty() {
12451103
formatter.buf.write_str(*piece)?;
12461104
}
1247-
(arg.formatter)(arg.value, &mut formatter)?;
1105+
arg.fmt(&mut formatter)?;
12481106
idx += 1;
12491107
}
12501108
}
@@ -1274,7 +1132,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
12741132
Ok(())
12751133
}
12761134

1277-
unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[Argument<'_>]) -> Result {
1135+
unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argument<'_>]) -> Result {
12781136
fmt.fill = arg.fill;
12791137
fmt.align = arg.align;
12801138
fmt.flags = arg.flags;
@@ -1292,10 +1150,10 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[Argument<'
12921150
let value = unsafe { args.get_unchecked(arg.position) };
12931151

12941152
// Then actually do some printing
1295-
(value.formatter)(value.value, fmt)
1153+
value.fmt(fmt)
12961154
}
12971155

1298-
unsafe fn getcount(args: &[Argument<'_>], cnt: &rt::Count) -> Option<usize> {
1156+
unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize> {
12991157
match *cnt {
13001158
rt::Count::Is(n) => Some(n),
13011159
rt::Count::Implied => None,
@@ -1878,7 +1736,7 @@ impl<'a> Formatter<'a> {
18781736
#[must_use]
18791737
#[stable(feature = "fmt_flags", since = "1.5.0")]
18801738
pub fn sign_plus(&self) -> bool {
1881-
self.flags & (1 << Flag::SignPlus as u32) != 0
1739+
self.flags & (1 << rt::Flag::SignPlus as u32) != 0
18821740
}
18831741

18841742
/// Determines if the `-` flag was specified.
@@ -1907,7 +1765,7 @@ impl<'a> Formatter<'a> {
19071765
#[must_use]
19081766
#[stable(feature = "fmt_flags", since = "1.5.0")]
19091767
pub fn sign_minus(&self) -> bool {
1910-
self.flags & (1 << Flag::SignMinus as u32) != 0
1768+
self.flags & (1 << rt::Flag::SignMinus as u32) != 0
19111769
}
19121770

19131771
/// Determines if the `#` flag was specified.
@@ -1935,7 +1793,7 @@ impl<'a> Formatter<'a> {
19351793
#[must_use]
19361794
#[stable(feature = "fmt_flags", since = "1.5.0")]
19371795
pub fn alternate(&self) -> bool {
1938-
self.flags & (1 << Flag::Alternate as u32) != 0
1796+
self.flags & (1 << rt::Flag::Alternate as u32) != 0
19391797
}
19401798

19411799
/// Determines if the `0` flag was specified.
@@ -1961,17 +1819,17 @@ impl<'a> Formatter<'a> {
19611819
#[must_use]
19621820
#[stable(feature = "fmt_flags", since = "1.5.0")]
19631821
pub fn sign_aware_zero_pad(&self) -> bool {
1964-
self.flags & (1 << Flag::SignAwareZeroPad as u32) != 0
1822+
self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0
19651823
}
19661824

19671825
// FIXME: Decide what public API we want for these two flags.
19681826
// https://github.com/rust-lang/rust/issues/48584
19691827
fn debug_lower_hex(&self) -> bool {
1970-
self.flags & (1 << Flag::DebugLowerHex as u32) != 0
1828+
self.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0
19711829
}
19721830

19731831
fn debug_upper_hex(&self) -> bool {
1974-
self.flags & (1 << Flag::DebugUpperHex as u32) != 0
1832+
self.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0
19751833
}
19761834

19771835
/// 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
25312389
// or not to zero extend, and then unconditionally set it to get the
25322390
// prefix.
25332391
if f.alternate() {
2534-
f.flags |= 1 << (Flag::SignAwareZeroPad as u32);
2392+
f.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32);
25352393

25362394
if f.width.is_none() {
25372395
f.width = Some((usize::BITS / 4) as usize + 2);
25382396
}
25392397
}
2540-
f.flags |= 1 << (Flag::Alternate as u32);
2398+
f.flags |= 1 << (rt::Flag::Alternate as u32);
25412399

25422400
let ret = LowerHex::fmt(&ptr_addr, f);
25432401

0 commit comments

Comments
 (0)