// /std/src/io/stdio.rs
pub struct StdinLock<'a> {
inner: MutexGuard<'a, BufReader<StdinRaw>>,
}
impl Stdin {
pub fn lock(&self) -> StdinLock<'static> {
// Locks this handle with 'static lifetime. This depends on the
// implementation detail that the underlying `Mutex` is static.
StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
}
}
Since we only have one stdin instance in a process, why does not Stdin::lock
just return a owned StdinLock
with MutexGuard<'static, ...>
instead?
StdinLock
's lifetime parameter exists for historical reasons, and removing it would be a breaking change. As detailed in the Announcing Rust 1.61.0 blog post:
Static handles for locked stdio
The three standard I/O streams --
Stdin
,Stdout
, andStderr
-- each have alock(&self)
to allow more control over synchronizing read and writes. However, they returned lock guards with a lifetime borrowed from&self
, so they were limited to the scope of the original handle. This was determined to be an unnecessary limitation, since the underlying locks were actually in static storage, so now the guards are returned with a'static
lifetime, disconnected from the handle.For example, a common error came from trying to get a handle and lock it in one statement:
// error[E0716]: temporary value dropped while borrowed let out = std::io::stdout().lock(); // ^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement // | // creates a temporary which is freed while still in use
Now the lock guard is
'static
, not borrowing from that temporary, so this works!