Small stream of consciousness warning:
I went to use flate2 today and wanted to use the Read/Write adaptors, and I almost immediately ran into an awkward situation. We have:
- Two extension traits,
FlateReadExt
andFlateWriteExt
... - ...both implemented for
File
(or any otherT: Read + Write
)... - ...with conflicting method names.
extern crate flate2;
use ::flate2::{FlateReadExt, FlateWriteExt, Compression};
use ::std::io::{Read,Write};
pub struct Struct;
impl Struct {
pub fn from_file(path: &::std::path::Path) -> Struct {
let mut bytes = vec![];
::std::fs::File::open(path).unwrap()
.gz_decode().unwrap()
.read_to_end(&mut bytes).unwrap();
panic!("TODO");
}
pub fn to_file(self, path: &::std::path::Path) {
let mut file =
::std::fs::File::create(path).unwrap()
.gz_encode(Compression::Best);
panic!("TODO");
}
}
Compiling ket-cereal v0.1.0 (file:///home/lampam/hex/rs/abom)
error[E0034]: multiple applicable items in scope
--> src/lib.rs:20:5
|
20 | .gz_encode(Compression::Best);
| ^^^^^^^^^ multiple `gz_encode` found
|
= note: candidate #1 is defined in an impl of the trait `flate2::FlateReadExt` for the type `_`
= note: candidate #2 is defined in an impl of the trait `flate2::FlateWriteExt` for the type `_`
error: aborting due to previous error
error: Could not compile `ket-cereal`.
The fix is to move the imports into the function definitions, but it seems like an unnecessary stumbling block.
More generally, I notice the API Guidelines don't currently have anything on extension traits, but I think they are worthy of mention as they have a number of different design considerations from typical traits.
...or then again, do they? As I was writing this, I initially cited the prelude
module pattern as a pattern that specifically caters to the needs of extension traits. But then I thought about it more and realized that the prelude
pattern is good for any trait whose methods you want to be readily available to the user. Thinking more about it, the best distinction I can think of that makes an extension trait An Extension Trait™ is that the documentation for one might say something to the effect of
please pretend this doesn't exist and just imagine that these methods are defined on
____
, oh and for the love of god don't use this as a generic bound
So maybe I'm just off my rocker on "extension traits" when they aren't even really a well-defined thing to begin with.
...Thoughts?
Note: right before posting I happened upon the RFC which apparently "defined" extension traits and conventions for them. The conventions are quite out of date, but it does have a clear definition I can agree with (traits not designed for generic use)