-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Arguments::as_str(). #74056
Add Arguments::as_str(). #74056
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
83cb097
to
8ef7248
Compare
Seems like making use of this in the macros would probably still be slightly worse for performance than the current approach (unless llvm is good enough to const-prop the condition here, but even so that's a compile time regression). I do think this is a useful API regardless, though. r? @sfackler for libs approval of unstable API |
I added #![feature(fmt_as_str)]
pub fn a() -> bool {
format_args!("asdf").as_str().is_some()
}
pub fn b() -> bool {
format_args!("asdf {}", 1).as_str().is_some()
} scratchpad::a:
mov al, 1
ret
scratchpad::b:
xor eax, eax
ret A more realistic example#![feature(fmt_as_str)]
extern "C" {
fn write_str(_: &str);
}
fn write_fmt(args: core::fmt::Arguments) {
if let Some(s) = args.as_str() {
// Avoid allocation, write the &str directly.
unsafe { write_str(s) };
} else {
// Format into a new String to get a &str.
unsafe { write_str(&args.to_string()) };
}
}
macro_rules! write {
($($t:tt)*) => {
write_fmt(format_args!($($t)*))
};
}
pub fn a() {
write!("hello world");
} scratchpad::a: ; Doesn't allocate, calls write_str directly.
lea rdi, [rip, +, .L__unnamed_1]
mov esi, 11
jmp qword, ptr, [rip, +, write_str@GOTPCREL] |
It's a bit of a shame that it has to return Changing (Note that this problem wouldn't have existed if |
We should change I think that we can remove However there is embedded code that actually relies on this optimization to work at all due to memory limitations so we need to provide some sort of transition to ensure their code keeps working. |
Sure, will work on that. I'll try to make test case to see if I can reproduce the program overhead in the non-optimized case, and see if I can find another way of avoiding that. |
The special case cannot be removed, as it'd break this: let a = "hello";
core::panic!(a); But the implementation can be changed to generate a |
I made it The panic_fmt(fmt::Arguments::new_v1(&[expr], &[])); to panic_fmt(fmt::Arguments::new_v1(&[""], &[fmt::ArgumentV1::new(&expr, |&e, f| f.write_str(e))])); because the first list can now only contain Two downsides:
1 might be fixed by restructuring the way fmt::Arguments works.
|
67c86e7
to
e8dcce0
Compare
For 2, could we try matching a |
Ah, that could work. Will try that tomorrow. |
e8dcce0
to
9587084
Compare
Updated it. The So, This means that both of the downsides mentioned above are gone for the |
9587084
to
c59bef9
Compare
88b14ac
to
0094a1e
Compare
…arth Rollup of 18 pull requests Successful merges: - rust-lang#71670 (Enforce even more the code blocks attributes check through rustdoc) - rust-lang#73930 (Make some Option methods const) - rust-lang#74009 (Fix MinGW `run-make-fulldeps` tests) - rust-lang#74056 (Add Arguments::as_str().) - rust-lang#74169 (Stop processing unreachable blocks when solving dataflow) - rust-lang#74251 (Teach bootstrap about target files vs target triples) - rust-lang#74288 (Fix src/test/run-make/static-pie/test-aslr.rs) - rust-lang#74300 (Use intra-doc links in core::iter module) - rust-lang#74364 (add lazy normalization regression tests) - rust-lang#74368 (Add CSS tidy check) - rust-lang#74394 (Remove leftover from emscripten fastcomp support) - rust-lang#74411 (Don't assign `()` to `!` MIR locals) - rust-lang#74416 (Use an UTF-8 locale for the linker.) - rust-lang#74424 (Move hir::Place to librustc_middle/hir) - rust-lang#74428 (docs: better demonstrate that None values are skipped as many times a…) - rust-lang#74438 (warn about uninitialized multi-variant enums) - rust-lang#74440 (Fix Arc::as_ptr docs) - rust-lang#74452 (intra-doc links: resolve modules in the type namespace) Failed merges: r? @ghost
I think this PR regressed the unstable feature of panicking during const-eval, see #51999 (comment) for further discussion. Also, the rust/library/std/src/macros.rs Lines 11 to 18 in c336478
Couldn't this benefit from |
Doesn't the fact that |
Yes, allowing that to work has to be a breaking change to the |
rust/library/std/src/panicking.rs Line 499 in 02fe309
Would be nice if that wasn't the case. But changing both |
I see, thanks.
This doesn't currently happen though, it seems? The panic machinery does not use
Ah, makes sense. Removing that arm from the macro would also break panicking during CTFE with |
|
Oh so the plan is to use this in std's panic handler to avoid the fomat machinery? Or is that just not worth it? Also, rust/library/core/src/panicking.rs Lines 44 to 50 in c336478
But I guess to replace that with |
Note that this comment isn't about either of the |
I think I finally understood what I am confused about here... what is the point of the Looks like they were needed because |
I don't think this is a plan right now. Might be nice?
Yes, that trick makes sure that |
Ah, the problem is that this code is accepted: (It shouldn't have, probably. But this is stable now.) core::panic!(&String::from("123")); This PR changes the lifetime for the |
Okay, that's what I figured, thanks. This still seems like something that is worth a more thorough discussion; #51999 (comment) shows that people have been using this so even breaking this on an edition change might be problematic. (Actually in that case the string is static, but it is not a literal...) Is there a tracking issue for the planned |
See discussion starting here: #74056 (comment) |
No, unfortunately, it's all part of discussions on other PRs and issues so far, like here: #67984 (comment) The lang team has asked for a concrete proposal for this (here #67984 (comment)), but I haven't had the time to work on that yet. (And I don't think anybody else did either.) |
Yeah, exactly. If |
Looks like the constant-evaluation code already assumed that the rust/compiler/rustc_mir/src/const_eval/machine.rs Lines 72 to 76 in 81a769f
|
I think that's just a bad comment, nothing in that code breaks if the string has a shorter lifetime. |
…ossible This involves branching, but as shown in [1], the compiler seems to have no problem resolving the branch at compile time if optimization is enabled. [1]: rust-lang/rust#74056 (comment)
There exist quite a few macros in the Rust ecosystem which use
format_args!()
for formatting, but special case the one-argument case for optimization:E.g. here, here, and here.
The problem with these is that a forgotten argument such as in
some_macro!("{}")
will not be diagnosed, but just prints"{}"
.With this PR, it is possible to handle the no-arguments case separately after
format_args!()
, while simplifying the macro. Then these macros can give the proper error about a missing argument, just likeprint!("{}")
does, while still using the same optimized implementation as before.This is even more important with RFC 2795, to make sure
some_macro!("{some_variable}")
works as expected.