File tree Expand file tree Collapse file tree 6 files changed +116
-33
lines changed Expand file tree Collapse file tree 6 files changed +116
-33
lines changed Original file line number Diff line number Diff line change 9797#![ feature( exact_size_is_empty) ]
9898#![ feature( exclusive_range_pattern) ]
9999#![ feature( extend_one) ]
100+ #![ feature( fmt_as_str) ]
100101#![ feature( fmt_internals) ]
101102#![ feature( fn_traits) ]
102103#![ feature( fundamental) ]
Original file line number Diff line number Diff line change @@ -101,9 +101,21 @@ macro_rules! vec {
101101/// ```
102102#[ macro_export]
103103#[ stable( feature = "rust1" , since = "1.0.0" ) ]
104+ #[ allow_internal_unstable( fmt_as_str) ]
104105macro_rules! format {
105106 ( $( $arg: tt) * ) => { {
106- let res = $crate:: fmt:: format( $crate:: __export:: format_args!( $( $arg) * ) ) ;
107- res
107+ // NOTE: `format_args!` borrows from temporaries. This means that
108+ // `match` is necessary to extend the lifetime of the temporaries until after
109+ // the `Arguments` is no longer used. The same pattern is used
110+ // inside `format_args!` itself.
111+ let r = match $crate:: __export:: format_args!( $( $arg) * ) {
112+ // HACK: We hope that constant propagation will make LLVM optimize out
113+ // this match.
114+ args => match args. as_str( ) {
115+ Some ( s) => $crate:: borrow:: ToOwned :: to_owned( s) ,
116+ None => $crate:: fmt:: format( args) ,
117+ }
118+ } ;
119+ r
108120 } }
109121}
Original file line number Diff line number Diff line change 1+ // min-llvm-version: 10.0.0
2+ // compile-flags: -C opt-level=3
3+ #![ crate_type = "rlib" ]
4+ #![ feature( format_args_capture) ]
5+
6+ // Make sure allocation not happen when result of `format!` is unused and
7+ // there are no formatting arguments.
8+
9+ // CHECK-LABEL: @format_wo_fmt_args
10+ // CHECK-NEXT: {{"_ZN[^:]+"}}:
11+ // CHECK-NEXT: ret
12+ #[ no_mangle]
13+ pub fn format_wo_fmt_args ( ) {
14+ format ! ( "" ) ;
15+ format ! ( "a long story" ) ;
16+ format ! ( "a long story {{" ) ;
17+ }
18+
19+ // CHECK-LABEL: @format_wo_fmt_args_ret
20+ // CHECK-NOT: Arguments
21+ #[ no_mangle]
22+ pub fn format_wo_fmt_args_ret ( ) -> String {
23+ format ! ( "a long story" )
24+ }
25+
26+ // CHECK-LABEL: @format_w_fmt_args_ret_1
27+ // CHECK: alloc::fmt::format
28+ #[ no_mangle]
29+ pub fn format_w_fmt_args_ret_1 ( n : usize ) -> String {
30+ format ! ( "a long story: {}" , n)
31+ }
32+
33+ // CHECK-LABEL: @format_w_fmt_args_ret_2
34+ // CHECK: core::fmt::ArgumentV1::from_usize
35+ // CHECK: alloc::fmt::format
36+ #[ no_mangle]
37+ pub fn format_w_fmt_args_ret_2 ( n : usize , width : usize ) -> String {
38+ format ! ( "a long story {n:width$}" )
39+ }
Original file line number Diff line number Diff line change 3030
3131
3232 ({
33- let res =
34- ((::alloc::fmt::format as
35- for<' r> fn(Arguments<' r>) -> String {format })(((::core::fmt::Arguments::new_v1
36- as
37- fn(&[&' static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test"
38- as
39- &str)]
40- as
41- [&str; 1])
42- as
43- &[&str; 1]),
44- (&(match (()
45- as
46- ())
47- {
48- ()
49- =>
50- ([]
51- as
52- [ArgumentV1; 0]),
53- }
54- as
55- [ArgumentV1; 0])
56- as
57- &[ArgumentV1; 0]))
58- as
59- Arguments))
60- as String);
61- (res as String)
33+ let r =
34+ (match ((::core::fmt::Arguments::new_v1 as
35+ fn(&[&' static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test"
36+ as
37+ &str)]
38+ as
39+ [&str; 1])
40+ as
41+ &[&str; 1]),
42+ (&(match (()
43+ as
44+ ())
45+ {
46+ ()
47+ =>
48+ ([]
49+ as
50+ [ArgumentV1; 0]),
51+ }
52+ as
53+ [ArgumentV1; 0])
54+ as
55+ &[ArgumentV1; 0]))
56+ as Arguments) {
57+ args =>
58+ (match ((args as Arguments).as_str() as
59+ Option<&str>) {
60+ Some(s) =>
61+ ((::alloc::borrow::ToOwned::to_owned as
62+ for<' r> fn(&' r str) -> <str as ToOwned>::Owned {<str as ToOwned>::to_owned})((s
63+ as
64+ &str))
65+ as String),
66+ None =>
67+ ((::alloc::fmt::format as
68+ for<' r> fn(Arguments<' r>) -> String {format})((args
69+ as
70+ Arguments))
71+ as String),
72+ } as String),
73+ } as String);
74+ (r as String)
6275 } as String);
6376 } as ())
6477pub type Foo = [i32; (3 as usize)];
Original file line number Diff line number Diff line change @@ -4,6 +4,8 @@ struct Value;
44static settings_dir: String = format ! ( "" ) ;
55//~^ ERROR calls in statics are limited to constant functions
66//~| ERROR calls in statics are limited to constant functions
7+ //~| ERROR calls in statics are limited to constant functions
8+ //~| ERROR calls in statics are limited to constant functions
79
810fn from_string ( _: String ) -> Value {
911 Value
Original file line number Diff line number Diff line change 11error[E0507]: cannot move out of static item `settings_dir`
2- --> $DIR/issue-64453.rs:14 :37
2+ --> $DIR/issue-64453.rs:16 :37
33 |
44LL | let settings_data = from_string(settings_dir);
55 | ^^^^^^^^^^^^ move occurs because `settings_dir` has type `String`, which does not implement the `Copy` trait
@@ -20,7 +20,23 @@ LL | static settings_dir: String = format!("");
2020 |
2121 = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
2222
23- error: aborting due to 3 previous errors
23+ error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
24+ --> $DIR/issue-64453.rs:4:31
25+ |
26+ LL | static settings_dir: String = format!("");
27+ | ^^^^^^^^^^^
28+ |
29+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
30+
31+ error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
32+ --> $DIR/issue-64453.rs:4:31
33+ |
34+ LL | static settings_dir: String = format!("");
35+ | ^^^^^^^^^^^
36+ |
37+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
38+
39+ error: aborting due to 5 previous errors
2440
2541Some errors have detailed explanations: E0015, E0507.
2642For more information about an error, try `rustc --explain E0015`.
You can’t perform that action at this time.
0 commit comments