Implementing and naming an extension trait for AsyncBufReadExt

For a crate I'm working on, I'm writing an extension trait that makes use of methods from tokio::io::AsyncBufReadExt (itself an extension trait on AsyncBufRead), and I'm unsure (a) what trait it should declare itself an extension of, and (b) what to name the resulting trait.

Should I:

  • Extend AsyncBufRead, name my trait AsyncBufReadExt, and use tokio::io::AsyncBufReadExt as _ in my code?
  • Extend AsyncBufReadExt and name my trait AsyncBufReadExtExt? (Surely that's not idiomatic!)
  • Other???

This would seem like the most sensible option to me; logically, Tokio's AsyncBufReadExt shouldn't really be used as a supertrait, since its sole purpose is to add methods to an AsyncBufRead object. It might still be worth naming your own trait something other than AsyncBufReadExt, though, so that users can import both your trait and Tokio's trait without aliases.

Since extension traits are often just imported at the top of a file[1] you might want to avoid naming it AsyncBufReadExt so users don't have to rename it in the import if they are already using the tokio extension trait


  1. sometimes added automatically by tooling like Rust Analyzer ↩︎

I don't want to give any recommendation here, because I don't really know what's most idiomatic, but I wanted to point out that it's also possible to export an unnameable module:

pub mod int_extension {
    pub trait IntExt {
        fn foo(&self);
    }
    impl IntExt for i32 {
        fn foo(&self) {
            println!("Hello!");
        }
    }
    pub mod prelude {
        pub use super::IntExt as _;
    }
}

use int_extension::prelude::*;

fn main() {
    5.foo();
}

(Playground)

I guess it's even possible to prohibit importing the trait in a named fashion (which makes it also sealed):

pub mod int_extension {
    mod private {
        pub trait IntExt {
            fn foo(&self);
        }
        impl IntExt for i32 {
            fn foo(&self) {
                println!("Hello!");
            }
        }
    }
    pub use private::IntExt as _;
}

use int_extension::*;

fn main() {
    5.foo();
}

(Playground)