Confusing compilation behavior involving AsFd

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

surdeus

Warning

This post was published 108 days ago. The information described in this article may have changed.

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