forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#96455 - dtolnay:writetmp, r=m-ou-se
Make write/print macros eagerly drop temporaries This PR fixes the 2 regressions in rust-lang#96434 (`println` and `eprintln`) and changes all the other similar macros (`write`, `writeln`, `print`, `eprint`) to match the old pre-rust-lang#94868 behavior of `println` and `eprintln`. argument position | before rust-lang#94868 | after rust-lang#94868 | after this PR --- |:---:|:---:|:---: `write!($tmp, "…", …)` | :rage: | :rage: | :smiley_cat: `write!(…, "…", $tmp)` | :rage: | :rage: | :smiley_cat: `writeln!($tmp, "…", …)` | :rage: | :rage: | :smiley_cat: `writeln!(…, "…", $tmp)` | :rage: | :rage: | :smiley_cat: `print!("…", $tmp)` | :rage: | :rage: | :smiley_cat: `println!("…", $tmp)` | :smiley_cat: | :rage: | :smiley_cat: `eprint!("…", $tmp)` | :rage: | :rage: | :smiley_cat: `eprintln!("…", $tmp)` | :smiley_cat: | :rage: | :smiley_cat: `panic!("…", $tmp)` | :smiley_cat: | :smiley_cat: | :smiley_cat: Example of code that is affected by this change: ```rust use std::sync::Mutex; fn main() { let mutex = Mutex::new(0); print!("{}", mutex.lock().unwrap()) /* no semicolon */ } ``` You can see several real-world examples like this in the Crater links at the top of rust-lang#96434. This code failed to compile prior to this PR as follows, but works after this PR. ```console error[E0597]: `mutex` does not live long enough --> src/main.rs:5:18 | 5 | print!("{}", mutex.lock().unwrap()) /* no semicolon */ | ^^^^^^^^^^^^--------- | | | borrowed value does not live long enough | a temporary with access to the borrow is created here ... 6 | } | - | | | `mutex` dropped here while still borrowed | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard` ```
- Loading branch information
Showing
4 changed files
with
118 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// check-pass | ||
|
||
use std::fmt::{self, Display}; | ||
|
||
struct Mutex; | ||
|
||
impl Mutex { | ||
fn lock(&self) -> MutexGuard { | ||
MutexGuard(self) | ||
} | ||
} | ||
|
||
struct MutexGuard<'a>(&'a Mutex); | ||
|
||
impl<'a> Drop for MutexGuard<'a> { | ||
fn drop(&mut self) { | ||
// Empty but this is a necessary part of the repro. Otherwise borrow | ||
// checker is fine with 'a dangling at the time that MutexGuard goes out | ||
// of scope. | ||
} | ||
} | ||
|
||
impl<'a> MutexGuard<'a> { | ||
fn write_fmt(&self, _args: fmt::Arguments) {} | ||
} | ||
|
||
impl<'a> Display for MutexGuard<'a> { | ||
fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { | ||
Ok(()) | ||
} | ||
} | ||
|
||
fn main() { | ||
let _write = { | ||
let out = Mutex; | ||
let mutex = Mutex; | ||
write!(out.lock(), "{}", mutex.lock()) /* no semicolon */ | ||
}; | ||
|
||
let _writeln = { | ||
let out = Mutex; | ||
let mutex = Mutex; | ||
writeln!(out.lock(), "{}", mutex.lock()) /* no semicolon */ | ||
}; | ||
|
||
let _print = { | ||
let mutex = Mutex; | ||
print!("{}", mutex.lock()) /* no semicolon */ | ||
}; | ||
|
||
let _println = { | ||
let mutex = Mutex; | ||
println!("{}", mutex.lock()) /* no semicolon */ | ||
}; | ||
|
||
let _eprint = { | ||
let mutex = Mutex; | ||
eprint!("{}", mutex.lock()) /* no semicolon */ | ||
}; | ||
|
||
let _eprintln = { | ||
let mutex = Mutex; | ||
eprintln!("{}", mutex.lock()) /* no semicolon */ | ||
}; | ||
|
||
let _panic = { | ||
let mutex = Mutex; | ||
panic!("{}", mutex.lock()) /* no semicolon */ | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters