Skip to content

Commit

Permalink
Make format_args!("literal") const.
Browse files Browse the repository at this point in the history
  • Loading branch information
m-ou-se committed Jul 9, 2021
1 parent 95fb131 commit e1092d4
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 29 deletions.
5 changes: 4 additions & 1 deletion compiler/rustc_builtin_macros/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ impl<'a, 'b> Context<'a, 'b> {
/// Actually builds the expression which the format_args! block will be
/// expanded to.
fn into_expr(self) -> P<ast::Expr> {
let is_literal = self.str_pieces.len() == 1 && self.args.is_empty();
let mut locals =
Vec::with_capacity((0..self.args.len()).map(|i| self.arg_unique_types[i].len()).sum());
let mut counts = Vec::with_capacity(self.count_args.len());
Expand Down Expand Up @@ -846,7 +847,9 @@ impl<'a, 'b> Context<'a, 'b> {
let args_slice = self.ecx.expr_addr_of(self.macsp, result);

// Now create the fmt::Arguments struct with all our locals we created.
let (fn_name, fn_args) = if self.all_pieces_simple {
let (fn_name, fn_args) = if is_literal {
("new_literal", vec![pieces])
} else if self.all_pieces_simple {
("new_v1", vec![pieces, args_slice])
} else {
// Build up the static array which will store our precompiled
Expand Down
9 changes: 9 additions & 0 deletions library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,15 @@ enum FlagV1 {
}

impl<'a> Arguments<'a> {
/// When using the format_args!() macro, this function is used to generate the
/// Arguments structure in case it's just a single string literal.
#[doc(hidden)]
#[inline]
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
pub const fn new_literal(pieces: &'a [&'static str; 1]) -> Arguments<'a> {
Arguments { pieces, fmt: None, args: &[] }
}

/// When using the format_args!() macro, this function is used to generate the
/// Arguments structure.
#[doc(hidden)]
Expand Down
7 changes: 1 addition & 6 deletions src/test/pretty/dollar-crate.pp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,5 @@
// pp-exact:dollar-crate.pp

fn main() {
{
::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"],
&match () {
() => [],
}));
};
{ ::std::io::_print(::core::fmt::Arguments::new_literal(&["rust\n"])); };
}
30 changes: 8 additions & 22 deletions src/test/pretty/issue-4264.pp
Original file line number Diff line number Diff line change
Expand Up @@ -32,29 +32,15 @@
({
let res =
((::alloc::fmt::format as
for<'r> fn(Arguments<'r>) -> String {format})(((::core::fmt::Arguments::new_v1
for<'r> fn(Arguments<'r>) -> String {format})(((::core::fmt::Arguments::new_literal
as
fn(&[&'static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test"
as
&str)]
as
[&str; 1])
as
&[&str; 1]),
(&(match (()
as
())
{
()
=>
([]
as
[ArgumentV1; 0]),
}
as
[ArgumentV1; 0])
as
&[ArgumentV1; 0]))
fn(&[&'static str; 1]) -> Arguments {Arguments::new_literal})((&([("test"
as
&str)]
as
[&str; 1])
as
&[&str; 1]))
as
Arguments))
as String);
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/consts/const-eval/format_args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![crate_type = "lib"]

const A: std::fmt::Arguments = format_args!("literal");

const B: std::fmt::Arguments = format_args!("{}", 123);
//~^ ERROR calls in constants are limited to
//~| ERROR calls in constants are limited to
//~| ERROR temporary value
32 changes: 32 additions & 0 deletions src/test/ui/consts/const-eval/format_args.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
--> $DIR/format_args.rs:5:32
|
LL | const B: std::fmt::Arguments = format_args!("{}", 123);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
--> $DIR/format_args.rs:5:32
|
LL | const B: std::fmt::Arguments = format_args!("{}", 123);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0716]: temporary value dropped while borrowed
--> $DIR/format_args.rs:5:32
|
LL | const B: std::fmt::Arguments = format_args!("{}", 123);
| ^^^^^^^^^^^^^^^^^^^^^^-
| | |
| | temporary value is freed at the end of this statement
| creates a temporary which is freed while still in use
| using this value as a constant requires that borrow lasts for `'static`
|
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0015, E0716.
For more information about an error, try `rustc --explain E0015`.

0 comments on commit e1092d4

Please sign in to comment.