Skip to content

Commit

Permalink
Use str::to_owned for format! without formatting arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
tesuji committed Sep 27, 2020
1 parent b836329 commit be1ea4b
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 33 deletions.
1 change: 1 addition & 0 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
#![feature(exact_size_is_empty)]
#![feature(exclusive_range_pattern)]
#![feature(extend_one)]
#![feature(fmt_as_str)]
#![feature(fmt_internals)]
#![feature(fn_traits)]
#![feature(fundamental)]
Expand Down
16 changes: 14 additions & 2 deletions library/alloc/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,21 @@ macro_rules! vec {
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(fmt_as_str)]
macro_rules! format {
($($arg:tt)*) => {{
let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
res
// NOTE: `format_args!` borrows from temporaries. This means that
// `match` is necessary to extend the lifetime of the temporaries until after
// the `Arguments` is no longer used. The same pattern is used
// inside `format_args!` itself.
let r = match $crate::__export::format_args!($($arg)*) {
// HACK: We hope that constant propagation will make LLVM optimize out
// this match.
args => match args.as_str() {
Some(s) => $crate::borrow::ToOwned::to_owned(s),
None => $crate::fmt::format(args),
}
};
r
}}
}
39 changes: 39 additions & 0 deletions src/test/codegen/issue-75742-format_without_fmt_args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// min-llvm-version: 10.0.0
// compile-flags: -C opt-level=3
#![crate_type = "rlib"]
#![feature(format_args_capture)]

// Make sure allocation not happen when result of `format!` is unused and
// there are no formatting arguments.

// CHECK-LABEL: @format_wo_fmt_args
// CHECK-NEXT: {{"_ZN[^:]+"}}:
// CHECK-NEXT: ret
#[no_mangle]
pub fn format_wo_fmt_args() {
format!("");
format!("a long story");
format!("a long story {{");
}

// CHECK-LABEL: @format_wo_fmt_args_ret
// CHECK-NOT: Arguments
#[no_mangle]
pub fn format_wo_fmt_args_ret() -> String {
format!("a long story")
}

// CHECK-LABEL: @format_w_fmt_args_ret_1
// CHECK: alloc::fmt::format
#[no_mangle]
pub fn format_w_fmt_args_ret_1(n: usize) -> String {
format!("a long story: {}", n)
}

// CHECK-LABEL: @format_w_fmt_args_ret_2
// CHECK: core::fmt::ArgumentV1::from_usize
// CHECK: alloc::fmt::format
#[no_mangle]
pub fn format_w_fmt_args_ret_2(n: usize, width: usize) -> String {
format!("a long story {n:width$}")
}
71 changes: 42 additions & 29 deletions src/test/pretty/issue-4264.pp
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,48 @@


({
let res =
((::alloc::fmt::format as
for<'r> fn(Arguments<'r>) -> String {format})(((::core::fmt::Arguments::new_v1
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]))
as
Arguments))
as String);
(res as String)
let r =
(match ((::core::fmt::Arguments::new_v1 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]))
as Arguments) {
args =>
(match ((args as Arguments).as_str() as
Option<&str>) {
Some(s) =>
((::alloc::borrow::ToOwned::to_owned as
for<'r> fn(&'r str) -> <str as ToOwned>::Owned {<str as ToOwned>::to_owned})((s
as
&str))
as String),
None =>
((::alloc::fmt::format as
for<'r> fn(Arguments<'r>) -> String {format})((args
as
Arguments))
as String),
} as String),
} as String);
(r as String)
} as String);
} as ())
pub type Foo = [i32; (3 as usize)];
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/borrowck/issue-64453.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ struct Value;
static settings_dir: String = format!("");
//~^ ERROR calls in statics are limited to constant functions
//~| ERROR calls in statics are limited to constant functions
//~| ERROR calls in statics are limited to constant functions
//~| ERROR calls in statics are limited to constant functions

fn from_string(_: String) -> Value {
Value
Expand Down
20 changes: 18 additions & 2 deletions src/test/ui/borrowck/issue-64453.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0507]: cannot move out of static item `settings_dir`
--> $DIR/issue-64453.rs:14:37
--> $DIR/issue-64453.rs:16:37
|
LL | let settings_data = from_string(settings_dir);
| ^^^^^^^^^^^^ move occurs because `settings_dir` has type `String`, which does not implement the `Copy` trait
Expand All @@ -20,7 +20,23 @@ LL | static settings_dir: String = format!("");
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 3 previous errors
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> $DIR/issue-64453.rs:4:31
|
LL | static settings_dir: String = format!("");
| ^^^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> $DIR/issue-64453.rs:4:31
|
LL | static settings_dir: String = format!("");
| ^^^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 5 previous errors

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

0 comments on commit be1ea4b

Please sign in to comment.