1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#![allow(missing_debug_implementations)]
#![unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]

//! These are the lang items used by format_args!().

use super::*;

#[lang = "format_placeholder"]
#[derive(Copy, Clone)]
pub struct Placeholder {
    pub position: usize,
    pub fill: char,
    pub align: Alignment,
    pub flags: u32,
    pub precision: Count,
    pub width: Count,
}

impl Placeholder {
    #[inline(always)]
    pub const fn new(
        position: usize,
        fill: char,
        align: Alignment,
        flags: u32,
        precision: Count,
        width: Count,
    ) -> Self {
        Self { position, fill, align, flags, precision, width }
    }
}

#[lang = "format_alignment"]
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Alignment {
    Left,
    Right,
    Center,
    Unknown,
}

/// 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"]
#[derive(Copy, Clone)]
pub enum Count {
    /// Specified with a literal number, stores the value
    Is(usize),
    /// Specified using `$` and `*` syntaxes, stores the index into `args`
    Param(usize),
    /// Not specified
    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
        }
    }

    /// Used by `format_args` when all arguments are gone after inlining,
    /// when using `&[]` would incorrectly allow for a bigger lifetime.
    ///
    /// This fails without format argument inlining, and that shouldn't be different
    /// when the argument is inlined:
    ///
    /// ```compile_fail,E0716
    /// let f = format_args!("{}", "a");
    /// println!("{f}");
    /// ```
    #[inline(always)]
    pub fn none() -> [Self; 0] {
        []
    }
}

/// 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 {}
};