Description
As reported here, the I/O safety feature introduces a breaking change.
Reduced standalone testcase (playground link):
use std::os::unix::io::FromRawFd;
use std::fs::File;
pub fn create_fd<F: FromRawFd>() -> F {
todo!()
}
fn main() {
let _f = File::from(create_fd());
}
error[E0283]: type annotations needed
--> src/main.rs:9:14
|
9 | let _f = File::from(create_fd());
| ^^^^^^^^^^ cannot infer type for type parameter `T` declared on the trait `From`
|
= note: cannot satisfy `File: From<_>`
note: required by `from`
--> /.../lib/rustlib/src/rust/library/core/src/convert/mod.rs:371:5
|
371 | fn from(_: T) -> Self;
| ^^^^^^^^^^^^^^^^^^^^^^
It's possible to change the code to avoid the error, for example by changing the let _f = ...
line to either of:
let _f = create_fd::<File>();
let _f: File = create_fd();
or, once I/O safety is stabilized, by changing create_fd
to return OwnedFd
instead of F: FromRawFd
. The reporter also reported that they've already fixed their own code. Nevertheless, it is breakage observed in real-world code.
The problem is caused by I/O safety adding an impl From<OwnedFd> for File
. We added these From
impls as an alternative to adding a new FromFd
trait. However, this means that File
now has multiple From
impls for types that implement AsRawFd
, so one can no longer do File::from(create_fd())
where create_fd
is defined like fn create_fd<F: FromRawFd>() -> F
, because it's now ambiguous which type it should use for F
.
So the questions here are:
- Is this breakage severe enough to block stabilization for I/O safety?
- If so, is there a way to fix it other than going back to adding a
FromFd
trait?