Flate2, and guidelines for extension traits

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 and FlateWriteExt...
  • ...both implemented for File (or any other T: 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)

2 Likes

I personally avoid using the extension traits when working with flate2 and instead just construct the adapter types directly.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.