Confusing compilation behavior involving AsFd

⚓ Rust    📅 2025-08-17    👤 surdeus    👁️ 6      

surdeus

I'm attempting to make some changes to the termios crate.

The relevant code can be found in this playground:

That code triggers this compiler error:

error[E0507]: cannot move out of `*writer` which is behind a mutable reference
  --> src/lib.rs:24:20
   |
24 |         let _raw = writer.into_raw_mode()?;
   |                    ^^^^^^ --------------- `*writer` moved due to this method call
   |                    |
   |                    move occurs because `*writer` has type `W`, which does not implement the `Copy` trait
   |
note: `IntoRawMode::into_raw_mode` takes ownership of the receiver `self`, which moves `*writer`
  --> src/lib.rs:13:22

I understand why this error occurs - writer is an &mut W, and the code is attempting to move the W elsewhere, which is illegal.

But now, try changing each instance of AsTermHandle /*AsFd*/ to AsFd. Here is another playground where the changes have been made:

This time, it compiles successfully. Huh? Why does this succeed when the previous code failed?

Neither AsTermHandle nor AsFd are Copy or Clone, so that can't be the answer.

I believe the answer has something to do with the AsFd trait - if you look in the docs, you'll find it has the following implementations:

impl<T: AsFd + ?Sized> AsFd for &T
impl<T: AsFd + ?Sized> AsFd for &mut T

Apparently these impl's were introduced in version 1.63.0 as some kind of "IO safety" feature.

But I would like my AsTermHandle trait to work in the same position as AsFd, and unfortunately, it seems to be impossible to do:

impl<T: std::os::fd::AsFd> AsTermHandle for T { /*...*/ }
impl<T: AsTermHandle + ?Sized> AsTermHandle for &T { /*...*/ }
impl<T: AsTermHandle + ?Sized> AsTermHandle for &mut T { /*...*/ }

If I try the implement the impl's above, the compiler fails with "conflicting traits." For completeness, here is a playground with the conflicting traits error:

So at this point, I'm stuck without performing a fairly substantial refactor of the termion crate, probably breaking library compatibility if I want to proceed.

Is there a relatively simple way to fix the conflicting traits error?

1 post - 1 participant

Read full topic

🏷️ Rust_feed