Working with extension feature restrictions

An example of the presence of the object-safe attribute Foo and the (potentially dangerous) attribute extension FooExt , implemented for all instances of Foo , is now becoming standard.

https://github.com/rust-lang/rfcs/pull/445

This is a problem for me in the case of Iterator<A> , since I have a library that overrides the default IteratorExt#last() method of the old iterator (the base library has an effective implementation of last() ). Now this is impossible, because for any A there will always be a contradictory implementation of IteratorExt , one that libcore already provides for all Iterator<A> .

iterator.rs:301:1: 306:2 error: conflicting implementations for trait `core::iter::IteratorExt` [E0119]

 iterator.rs:301 impl<'a, K: Key> iter::IteratorExt<Vec<u8>> for ValueIterator<'a,K,Vec<u8>> { iterator.rs:302 fn last(&mut self) -> Option<Vec<u8>> { iterator.rs:303 self.seek_last(); iterator.rs:304 Some(self.value()) iterator.rs:305 } iterator.rs:306 } ... 

Now, as far as I can see, I have two options:

  • has its own trait and my own implementation of last() . This would mean that it conflicts if IteratorExt imported, if not used carefully. It may also accidentally use an ineffective version of last() if using a version from IteratorExt . I would lose convenient access to IteratorExt .
  • has its own trait and name the method ( seek_last() ) in different ways. Disadvantage: I ask the user to study the vocabulary and always support my method compared to IteratorExt . Same problem: I would like to avoid accidentally using last() .

Is there any other, better, solution that I am missing?

+8
iterator traits rust
source share
2 answers

As of rustc 0.13.0-nightly (8bca470c5 2014-12-08 00:12:30 +0000) defining last() as a built-in method for your type should work.

 #[deriving(Copy)] struct Foo<T> {t: T} impl<T> Iterator<T> for Foo<T> { fn next(&mut self) -> Option<T> { None } } // this does not work // error: conflicting implementations for trait `core::iter::IteratorExt` [E0119] // impl<T> IteratorExt<T> for Foo<T> { // fn last(mut self) -> Option<T> { None } //} // but this currently does impl<T> Foo<T> { fn last(mut self) -> Option<T> { Some(self.t) } } fn main() { let mut t = Foo{ t: 3u }; println!("{}", t.next()) println!("{}", t.last()) // last has been "shadowed" by our impl println!("{}", t.nth(3)) // other IteratorExt methods are still available } 

Since you should not use extension traits as common boundaries (but just to provide additional methods), this should theoretically work for your scenario, since you can have your own type and its impl in the same box.

Users of your type will use their own last method, not the one on IteratorExt , but will still be able to use other methods on IteratorExt .

+2
source share

last should be moved to Iterator , not IteratorExt .

IteratorExt is required when using Box<Iterator> objects to allow calling common methods on them (for example, map ), because you cannot put a common method in a vtable. However, last not generic, so you can put it in an Iterator .

0
source share

All Articles