Skip to content

Commit 6cb75d8

Browse files
Rollup merge of #140544 - m-ou-se:format-args-const-cleanup, r=fee1-dead
Clean up "const" situation in format_args!(). This cleans up the "const" situation in the format_args!() expansion/lowering. Rather than marking the Argument::new_display etc. functions as non-const, this marks the Arguments::new_v1 functions as non-const. Example expansion/lowering of format_args!() in const: ```rust // Error: cannot call non-const formatting macro in constant functions const { fmt::Arguments::new_v1( // Now the error is produced here. &["Hello, ", "!\n"], &[ fmt::Argument::new_display(&world) // The error used to be produced here. ], ) } ```
2 parents 786a53d + 86c6e79 commit 6cb75d8

File tree

7 files changed

+77
-63
lines changed

7 files changed

+77
-63
lines changed

compiler/rustc_const_eval/src/check_consts/ops.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ fn build_error_for_const_call<'tcx>(
352352
);
353353
err
354354
}
355-
_ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentMethods) => {
355+
_ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::FmtArgumentsNew) => {
356356
ccx.dcx().create_err(errors::NonConstFmtMacroCall {
357357
span,
358358
kind: ccx.const_kind(),

compiler/rustc_span/src/symbol.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ symbols! {
174174
Arc,
175175
ArcWeak,
176176
Argument,
177-
ArgumentMethods,
178177
ArrayIntoIter,
179178
AsMut,
180179
AsRef,
@@ -249,6 +248,7 @@ symbols! {
249248
Error,
250249
File,
251250
FileType,
251+
FmtArgumentsNew,
252252
Fn,
253253
FnMut,
254254
FnOnce,

library/core/src/fmt/mod.rs

-35
Original file line numberDiff line numberDiff line change
@@ -622,44 +622,9 @@ pub struct Arguments<'a> {
622622
args: &'a [rt::Argument<'a>],
623623
}
624624

625-
/// Used by the format_args!() macro to create a fmt::Arguments object.
626625
#[doc(hidden)]
627626
#[unstable(feature = "fmt_internals", issue = "none")]
628627
impl<'a> Arguments<'a> {
629-
#[inline]
630-
pub const fn new_const<const N: usize>(pieces: &'a [&'static str; N]) -> Self {
631-
const { assert!(N <= 1) };
632-
Arguments { pieces, fmt: None, args: &[] }
633-
}
634-
635-
/// When using the format_args!() macro, this function is used to generate the
636-
/// Arguments structure.
637-
#[inline]
638-
pub const fn new_v1<const P: usize, const A: usize>(
639-
pieces: &'a [&'static str; P],
640-
args: &'a [rt::Argument<'a>; A],
641-
) -> Arguments<'a> {
642-
const { assert!(P >= A && P <= A + 1, "invalid args") }
643-
Arguments { pieces, fmt: None, args }
644-
}
645-
646-
/// Specifies nonstandard formatting parameters.
647-
///
648-
/// An `rt::UnsafeArg` is required because the following invariants must be held
649-
/// in order for this function to be safe:
650-
/// 1. The `pieces` slice must be at least as long as `fmt`.
651-
/// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`.
652-
/// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
653-
#[inline]
654-
pub const fn new_v1_formatted(
655-
pieces: &'a [&'static str],
656-
args: &'a [rt::Argument<'a>],
657-
fmt: &'a [rt::Placeholder],
658-
_unsafe_arg: rt::UnsafeArg,
659-
) -> Arguments<'a> {
660-
Arguments { pieces, fmt: Some(fmt), args }
661-
}
662-
663628
/// Estimates the length of the formatted text.
664629
///
665630
/// This is intended to be used for setting initial `String` capacity

library/core/src/fmt/rt.rs

+69-20
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
#![allow(missing_debug_implementations)]
22
#![unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
33

4-
//! These are the lang items used by format_args!().
4+
//! All types and methods in this file are used by the compiler in
5+
//! the expansion/lowering of format_args!().
6+
//!
7+
//! Do not modify them without understanding the consequences for the format_args!() macro.
58
69
use super::*;
710
use crate::hint::unreachable_unchecked;
@@ -110,46 +113,45 @@ macro_rules! argument_new {
110113
};
111114
}
112115

113-
#[rustc_diagnostic_item = "ArgumentMethods"]
114116
impl Argument<'_> {
115117
#[inline]
116-
pub fn new_display<T: Display>(x: &T) -> Argument<'_> {
118+
pub const fn new_display<T: Display>(x: &T) -> Argument<'_> {
117119
argument_new!(T, x, <T as Display>::fmt)
118120
}
119121
#[inline]
120-
pub fn new_debug<T: Debug>(x: &T) -> Argument<'_> {
122+
pub const fn new_debug<T: Debug>(x: &T) -> Argument<'_> {
121123
argument_new!(T, x, <T as Debug>::fmt)
122124
}
123125
#[inline]
124-
pub fn new_debug_noop<T: Debug>(x: &T) -> Argument<'_> {
126+
pub const fn new_debug_noop<T: Debug>(x: &T) -> Argument<'_> {
125127
argument_new!(T, x, |_: &T, _| Ok(()))
126128
}
127129
#[inline]
128-
pub fn new_octal<T: Octal>(x: &T) -> Argument<'_> {
130+
pub const fn new_octal<T: Octal>(x: &T) -> Argument<'_> {
129131
argument_new!(T, x, <T as Octal>::fmt)
130132
}
131133
#[inline]
132-
pub fn new_lower_hex<T: LowerHex>(x: &T) -> Argument<'_> {
134+
pub const fn new_lower_hex<T: LowerHex>(x: &T) -> Argument<'_> {
133135
argument_new!(T, x, <T as LowerHex>::fmt)
134136
}
135137
#[inline]
136-
pub fn new_upper_hex<T: UpperHex>(x: &T) -> Argument<'_> {
138+
pub const fn new_upper_hex<T: UpperHex>(x: &T) -> Argument<'_> {
137139
argument_new!(T, x, <T as UpperHex>::fmt)
138140
}
139141
#[inline]
140-
pub fn new_pointer<T: Pointer>(x: &T) -> Argument<'_> {
142+
pub const fn new_pointer<T: Pointer>(x: &T) -> Argument<'_> {
141143
argument_new!(T, x, <T as Pointer>::fmt)
142144
}
143145
#[inline]
144-
pub fn new_binary<T: Binary>(x: &T) -> Argument<'_> {
146+
pub const fn new_binary<T: Binary>(x: &T) -> Argument<'_> {
145147
argument_new!(T, x, <T as Binary>::fmt)
146148
}
147149
#[inline]
148-
pub fn new_lower_exp<T: LowerExp>(x: &T) -> Argument<'_> {
150+
pub const fn new_lower_exp<T: LowerExp>(x: &T) -> Argument<'_> {
149151
argument_new!(T, x, <T as LowerExp>::fmt)
150152
}
151153
#[inline]
152-
pub fn new_upper_exp<T: UpperExp>(x: &T) -> Argument<'_> {
154+
pub const fn new_upper_exp<T: UpperExp>(x: &T) -> Argument<'_> {
153155
argument_new!(T, x, <T as UpperExp>::fmt)
154156
}
155157
#[inline]
@@ -200,15 +202,8 @@ impl Argument<'_> {
200202
/// let f = format_args!("{}", "a");
201203
/// println!("{f}");
202204
/// ```
203-
///
204-
/// This function should _not_ be const, to make sure we don't accept
205-
/// format_args!() and panic!() with arguments in const, even when not evaluated:
206-
///
207-
/// ```compile_fail,E0015
208-
/// const _: () = if false { panic!("a {}", "a") };
209-
/// ```
210205
#[inline]
211-
pub fn none() -> [Self; 0] {
206+
pub const fn none() -> [Self; 0] {
212207
[]
213208
}
214209
}
@@ -229,3 +224,57 @@ impl UnsafeArg {
229224
Self { _private: () }
230225
}
231226
}
227+
228+
/// Used by the format_args!() macro to create a fmt::Arguments object.
229+
#[doc(hidden)]
230+
#[unstable(feature = "fmt_internals", issue = "none")]
231+
#[rustc_diagnostic_item = "FmtArgumentsNew"]
232+
impl<'a> Arguments<'a> {
233+
#[inline]
234+
pub const fn new_const<const N: usize>(pieces: &'a [&'static str; N]) -> Self {
235+
const { assert!(N <= 1) };
236+
Arguments { pieces, fmt: None, args: &[] }
237+
}
238+
239+
/// When using the format_args!() macro, this function is used to generate the
240+
/// Arguments structure.
241+
///
242+
/// This function should _not_ be const, to make sure we don't accept
243+
/// format_args!() and panic!() with arguments in const, even when not evaluated:
244+
///
245+
/// ```compile_fail,E0015
246+
/// const _: () = if false { panic!("a {}", "a") };
247+
/// ```
248+
#[inline]
249+
pub fn new_v1<const P: usize, const A: usize>(
250+
pieces: &'a [&'static str; P],
251+
args: &'a [rt::Argument<'a>; A],
252+
) -> Arguments<'a> {
253+
const { assert!(P >= A && P <= A + 1, "invalid args") }
254+
Arguments { pieces, fmt: None, args }
255+
}
256+
257+
/// Specifies nonstandard formatting parameters.
258+
///
259+
/// An `rt::UnsafeArg` is required because the following invariants must be held
260+
/// in order for this function to be safe:
261+
/// 1. The `pieces` slice must be at least as long as `fmt`.
262+
/// 2. Every `rt::Placeholder::position` value within `fmt` must be a valid index of `args`.
263+
/// 3. Every `rt::Count::Param` within `fmt` must contain a valid index of `args`.
264+
///
265+
/// This function should _not_ be const, to make sure we don't accept
266+
/// format_args!() and panic!() with arguments in const, even when not evaluated:
267+
///
268+
/// ```compile_fail,E0015
269+
/// const _: () = if false { panic!("a {:1}", "a") };
270+
/// ```
271+
#[inline]
272+
pub fn new_v1_formatted(
273+
pieces: &'a [&'static str],
274+
args: &'a [rt::Argument<'a>],
275+
fmt: &'a [rt::Placeholder],
276+
_unsafe_arg: rt::UnsafeArg,
277+
) -> Arguments<'a> {
278+
Arguments { pieces, fmt: Some(fmt), args }
279+
}
280+
}

tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121
StorageDead(_18);
122122
_16 = &_17;
123123
_15 = &(*_16);
124-
_11 = Arguments::<'_>::new_v1::<3, 2>(move _12, move _15) -> [return: bb5, unwind unreachable];
124+
_11 = core::fmt::rt::<impl Arguments<'_>>::new_v1::<3, 2>(move _12, move _15) -> [return: bb5, unwind unreachable];
125125
}
126126

127127
bb5: {

tests/pretty/issue-4264.pp

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
((::alloc::fmt::format as
3535
for<'a> fn(Arguments<'a>) -> String {format})(((format_arguments::new_const
3636
as
37-
fn(&[&'static str; 1]) -> Arguments<'_> {Arguments::<'_>::new_const::<1>})((&([("test"
37+
fn(&[&'static str; 1]) -> Arguments<'_> {core::fmt::rt::<impl Arguments<'_>>::new_const::<1>})((&([("test"
3838
as &str)] as [&str; 1]) as &[&str; 1])) as Arguments<'_>))
3939
as String)
4040
} as String)) as String);

tests/ui/consts/const-eval/format.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
error[E0015]: cannot call non-const formatting macro in constant functions
2-
--> $DIR/format.rs:2:13
2+
--> $DIR/format.rs:2:5
33
|
44
LL | panic!("{:?}", 0);
5-
| ^^^^
5+
| ^^^^^^^^^^^^^^^^^
66
|
77
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
88

99
error[E0015]: cannot call non-const formatting macro in constant functions
10-
--> $DIR/format.rs:7:15
10+
--> $DIR/format.rs:7:5
1111
|
1212
LL | println!("{:?}", 0);
13-
| ^^^^
13+
| ^^^^^^^^^^^^^^^^^^^
1414
|
1515
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
1616
= 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)

0 commit comments

Comments
 (0)