Automatic trait implementation does not work - rust

On the code below, you can see that I forced the implementation of A for everything that implements AsRef<[T]> and Index[T], so B should implement it, because it implements both of these. However this is not the case. Why?
use std::convert::{AsMut, AsRef};
use std::ops::{Index, IndexMut};
use std::slice::SliceIndex;
pub trait A<T, I: SliceIndex<[T], Output = T>>:
AsRef<[T]> + Index<I, Output = T>
{
fn len(&self) -> usize;
}
impl<
T: AsRef<[T]> + Index<I, Output = T>,
I: SliceIndex<[T], Output = T>,
> A<T, I> for T
{
fn len(&self) -> usize {
self.as_ref().len()
}
}
struct B<'a, T>{
data: &'a mut [T]
}
impl<'a, T> AsRef<[T]> for B<'a, T> {
fn as_ref(&self) -> &[T] {
self.data
}
}
impl<'a, T, I: SliceIndex<[T], Output = T>> Index<I> for B<'a, T> {
type Output = T;
fn index(
&self,
v: I,
) -> &Self::Output {
&self.as_ref()[v]
}
}
fn something<'a, T>(r: &'a mut[T]) -> Box<dyn A<T, usize>> {
let a = B{data: r};
Box::new(a)
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=aa2353139f3d097e2497ed700d678ed3
Error:
error[E0277]: the trait bound `B<'_, T>: A<T, usize>` is not satisfied
--> src/lib.rs:46:5
|
46 | Box::new(a)
| ^^^^^^^^^^^ the trait `A<T, usize>` is not implemented for `B<'_, T>`
|
= note: required for the cast to the object type `dyn A<T, usize, Output = T>`

You need to introduce an additional type parameter on the blanket impl for A:
impl<T, I, V> A<T, I> for V
where
V: AsRef<[T]> + Index<I, Output = T>,
I: SliceIndex<[T], Output = T>,
{
fn len(&self) -> usize {
self.as_ref().len()
}
}
After fixing that, you'll get a lifetime error since the trait object returned in the box infers a 'static lifetime, so you'll need to bind it to the input slice's 'a lifetime.
fn something<'a, T>(r: &'a mut [T]) -> Box<dyn A<T, usize> + 'a> {
let a = B { data: r };
Box::new(a)
}

Related

Generic trait for all containers implementing iter()

I'm trying to implement a trait for all containers that implement iter(), ie. for all containers that provide an IntoIterator<Item=&'a T>. I've tried this, but unfortunately, even for the simplest case it is failing. Maybe someone knows what I'm doing wrong?
trait Monotonic<'a, T: 'a + ?Sized> {
fn is_monotonic(&mut self) -> bool {
return true;
}
}
impl<'a, T: 'a + ?Sized, C> Monotonic<'a, T> for C
where C: IntoIterator<Item=&'a T> + ?Sized {}
fn main() {
let v = vec![1u32, 2u32, 3u32];
if v.is_monotonic() {
print!("Is monotonic!");
}
}
The compiler complains about not satisfied bounds:
error[E0599]: the method `is_monotonic` exists for struct `Vec<u32>`, but its trait bounds were not satisfied
--> src/test.rs:13:10
|
13 | if v.is_monotonic() {
| ^^^^^^^^^^^^ method cannot be called on `Vec<u32>` due to unsatisfied trait bounds
--> /rustc/fc594f15669680fa70d255faec3ca3fb507c3405/library/alloc/src/vec/mod.rs:400:1
|
| = note: doesn't satisfy `<Vec<u32> as IntoIterator>::Item = &_`
= note: doesn't satisfy `Vec<u32>: Monotonic<'_, _>`
|
note: trait bound `[u32]: IntoIterator` was not satisfied
--> src/test.rs:8:10
|
7 | impl<'a, T: 'a + ?Sized, C> Monotonic<'a, T> for C
| ---------------- -
8 | where C: IntoIterator<Item=&'a T> + ?Sized {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`<Vec<u32> as IntoIterator>::Item = &_`
`<[u32] as IntoIterator>::Item = &_`
--> src/test.rs:8:23
|
7 | impl<'a, T: 'a + ?Sized, C> Monotonic<'a, T> for C
| ---------------- -
8 | where C: IntoIterator<Item=&'a T> + ?Sized {}
| ^^^^^^^^^^ unsatisfied trait bound introduced here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.
I've already tried to solve this on my own, but after several attempts I'm at a point where some help would be highly appreciated!
According to its documentation, Vec<T> implements the following IntoIterator traits:
IntoIterator<Item = &'a T> for &'a Vec<T, A>
IntoIterator<Item = &'a mut T> for &'a mut Vec<T, A>
IntoIterator<Item = T> for Vec<T, A>
The variable v you are calling it on is a Vec<u32>, which only implements IntoIterator<Item = u32>, and not any kind of &'a u32 as your trait requires.
There are a couple of solutions. The first one is to run the code on &v:
trait Monotonic<'a, T: 'a + ?Sized> {
fn is_monotonic(&mut self) -> bool {
return true;
}
}
impl<'a, T: 'a + ?Sized, C> Monotonic<'a, T> for C where C: IntoIterator<Item = &'a T> + ?Sized {}
fn main() {
let v = vec![1u32, 2u32, 3u32];
if (&v).is_monotonic() {
print!("Is monotonic!");
}
}
Although that's probably not what you want, because I read from your question that you want your Monotonic trait to be implemented as generically as possible. For that, simply remove the & requirement:
trait Monotonic<'a, T: 'a + ?Sized> {
fn is_monotonic(&mut self) -> bool {
return true;
}
}
impl<'a, T: 'a + ?Sized, C> Monotonic<'a, T> for C where C: IntoIterator<Item = T> + ?Sized {}
fn main() {
let mut v = vec![1u32, 2u32, 3u32];
if v.is_monotonic() {
print!("Is monotonic!");
}
}
Couple of remarks concerning your current code structure, though:
While this technically compiles, it won't be possible to implement your function. IntoIterator consumes the object you call it on, but your is_monotonic function only has &mut access to it, so you won't ever be able to call into_iter here.
What you probably want instead is to have is_monotonic consume the value, but then only implement it for &T.
Your Monotonic function doesn't require any generic parameters, so remove them.
trait Monotonic {
fn is_monotonic(self) -> bool;
}
impl<'a, T, C> Monotonic for &'a C
where
&'a C: IntoIterator<Item = T>,
{
fn is_monotonic(self) -> bool {
let mut iter = self.into_iter();
// Do something with iter
let x = iter.next().unwrap();
// Return result
true
}
}
fn main() {
let v = vec![1u32, 2u32, 3u32];
if v.is_monotonic() {
print!("Is monotonic!");
}
}
Here is an example implementation of is_monotonic, assuming it means monotonic rising:
trait Monotonic {
fn is_monotonic(self) -> bool;
}
impl<'a, T, C> Monotonic for &'a C
where
&'a C: IntoIterator<Item = T>,
T: PartialOrd,
{
fn is_monotonic(self) -> bool {
let mut iter = self.into_iter();
if let Some(first) = iter.next() {
let mut previous = first;
for next in iter {
if !next.ge(&previous) {
return false;
}
previous = next;
}
true
} else {
// An iterator without elements is monotonic.
// Although that's probably up for philosophical debate.
true
}
}
}
fn main() {
let v = vec![1u32, 2u32, 3u32];
if v.is_monotonic() {
println!("Is monotonic!");
}
println!("{:?}", v);
}
Is monotonic!
[1, 2, 3]

Trouble with stricter lifetime requirements when implementing FromIterator for LazyList

I was playing with the code from this answer but the FromIterator impl does not compile any more:
error[E0276]: impl has stricter requirements than trait --> src/lib.rs:184:9
| 184 | fn from_iter<I: IntoIterator<Item = T> + 'a>(itrbl: I) -> LazyList<'a, T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `I: 'a`
For more information about this error, try `rustc --explain E0276`.
The slightly updated code is on the playground.
// only necessary because Box<FnOnce() -> R> doesn't work...
mod thunk {
pub trait Invoke<R = ()> {
fn invoke(self: Box<Self>) -> R;
}
impl<R, F: FnOnce() -> R> Invoke<R> for F {
#[inline(always)]
fn invoke(self: Box<F>) -> R { (*self)() }
}
}
// Lazy is lazily evaluated contained value using the above Invoke trait
// instead of the desire Box<FnOnce() -> T> or a stable FnBox (currently not)...
pub mod lazy {
use crate::thunk::Invoke;
use std::cell::UnsafeCell;
use std::mem::replace;
use std::ops::Deref;
// Lazy is lazily evaluated contained value using the above Invoke trait
// instead of the desire Box<FnOnce() -> T> or a stable FnBox (currently not)...
pub struct Lazy<'a, T: 'a>(UnsafeCell<LazyState<'a, T>>);
enum LazyState<'a, T: 'a> {
Unevaluated(Box<dyn Invoke<T> + 'a>),
EvaluationInProgress,
Evaluated(T),
}
use self::LazyState::*;
impl<'a, T: 'a> Lazy<'a, T> {
#[inline]
pub fn new<F: 'a + FnOnce() -> T>(func: F) -> Lazy<'a, T> {
Lazy(UnsafeCell::new(Unevaluated(Box::new(func))))
}
#[inline]
pub fn evaluated(val: T) -> Lazy<'a, T> {
Lazy(UnsafeCell::new(Evaluated(val)))
}
#[inline(always)]
fn force(&self) {
unsafe {
match *self.0.get() {
Evaluated(_) => {}, // nothing required; already Evaluated
EvaluationInProgress => panic!("Lazy::force called recursively!!!"),
_ => {
let ue = replace(&mut *self.0.get(), EvaluationInProgress);
if let Unevaluated(thnk) = ue {
*self.0.get() = Evaluated(thnk.invoke());
} // no other possiblity!
}
}
}
}
#[inline]
pub fn unwrap<'b>(self) -> T where T: 'b { // consumes the object to produce the value
self.force(); // evaluatate if not evealutated
match { self.0.into_inner() } {
Evaluated(v) => v,
_ => unreachable!() // previous code guarantees never not Evaluated
}
}
}
impl<'a, T: 'a> Deref for Lazy<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.force(); // evaluatate if not evalutated
match *unsafe { &*self.0.get() } {
Evaluated(ref v) => v,
_ => unreachable!(),
}
}
}
}
// LazyList is an immutable lazily-evaluated persistent (memoized) singly-linked list
// similar to lists in Haskell, although here only tails are lazy...
// depends on the contained type being Clone so that the LazyList can be
// extracted from the reference-counted Rc heap objects in which embedded.
pub mod lazylist {
use crate::lazy::Lazy;
use std::rc::Rc;
use std::iter::FromIterator;
use std::mem::{replace, swap};
#[derive(Clone)]
pub enum LazyList<'a, T: 'a + Clone> {
Empty,
Cons(T, RcLazyListNode<'a, T>),
}
pub use self::LazyList::Empty;
use self::LazyList::Cons;
type RcLazyListNode<'a, T> = Rc<Lazy<'a, LazyList<'a, T>>>;
// impl<'a, T:'a> !Sync for LazyList<'a, T> {}
impl<'a, T: 'a + Clone> LazyList<'a, T> {
#[inline]
pub fn singleton(v: T) -> LazyList<'a, T> {
Cons(v, Rc::new(Lazy::evaluated(Empty)))
}
#[inline]
pub fn cons<F>(v: T, cntf: F) -> LazyList<'a, T>
where F: 'a + FnOnce() -> LazyList<'a, T>
{
Cons(v, Rc::new(Lazy::new(cntf)))
}
#[inline]
pub fn head(&self) -> &T {
if let Cons(ref hd, _) = *self {
return hd;
}
panic!("LazyList::head called on an Empty LazyList!!!")
}
#[inline]
pub fn tail<'b>(&'b self) -> &'b Lazy<'a, LazyList<'a, T>> {
if let Cons(_, ref rlln) = *self {
return &*rlln;
}
panic!("LazyList::tail called on an Empty LazyList!!!")
}
#[inline]
pub fn unwrap(self) -> (T, RcLazyListNode<'a, T>) {
// consumes the object
if let Cons(hd, rlln) = self {
return (hd, rlln);
}
panic!("LazyList::unwrap called on an Empty LazyList!!!")
}
#[inline]
fn iter(&self) -> Iter<'a, T> {
Iter(self)
}
}
impl<'a, T: 'a + Clone> Iterator for LazyList<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match replace(self, Empty) {
Cons(hd, rlln) => {
let mut newll = (*rlln).clone();
swap(self, &mut newll); // self now contains tail, newll contains the Empty
Some(hd)
}
_ => None,
}
}
}
pub struct Iter<'a, T: 'a + Clone>(*const LazyList<'a, T>);
impl<'a, T: 'a + Clone> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
unsafe {
if let LazyList::Cons(ref v, ref r) = *self.0 {
self.0 = &***r;
Some(v)
} else {
None
}
}
}
}
impl<'i, 'l, T: 'i + Clone> IntoIterator for &'l LazyList<'i, T> {
type Item = &'i T;
type IntoIter = Iter<'i, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T: 'a + Clone, > FromIterator<T> for LazyList<'a, T> {
fn from_iter<I: IntoIterator<Item = T> + 'a>(itrbl: I) -> LazyList<'a, T> {
let itr = itrbl.into_iter();
#[inline(always)]
fn next_iter<'b, R, Itr>(mut iter: Itr) -> LazyList<'b, R>
where R: 'b + Clone,
Itr: 'b + Iterator<Item = R>
{
match iter.next() {
Some(val) => LazyList::cons(val, move || next_iter(iter)),
None => Empty,
}
}
next_iter(itr)
}
}
}
Unfortunately I've exhausted ideas on how to try and fix this.
The code in the question (though not in the referenced answer, which has since been updated) relies on a soundness bug in older versions of the compiler (#18937) which has since been fixed.
It is not possible to implement FromIterator for LazyList, or indeed for any data structure, by storing the iterator inside the structure. This is because the FromIterator trait allows the implementor (Self) to outlive the iterator type (I::IntoIter). That the compiler ever accepted it was an oversight.
When copying code from the internet, be conscious of the age of the source. This code is also out of date in several other respects, notably:
it uses Rust 2015-style paths
it omits dyn on trait object types
the Invoke workaround is no longer needed, since dyn FnOnce() -> T works properly now.

How do I return the result of get_mut from a HashMap or a HashSet?

I'm trying to wrap a HashMap, as defined below, to return a mutable reference from a HashMap:
use std::{collections::HashMap, marker::PhantomData};
struct Id<T>(usize, PhantomData<T>);
pub struct IdCollection<T>(HashMap<Id<T>, T>);
impl<'a, T> std::ops::Index<Id<T>> for &'a mut IdCollection<T> {
type Output = &'a mut T;
fn index(&mut self, id: &'a Id<T>) -> Self::Output {
self.0.get_mut(id).unwrap()
}
}
And the resulting error:
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 54:5...
--> src/id_container.rs:54:5
|
54 | / fn index(&mut self, id: &'a Id<T>) -> Self::Output {
55 | | self.0.get_mut(id).unwrap()
56 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/id_container.rs:55:9
|
55 | self.0.get_mut(id).unwrap()
| ^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 52:6...
--> src/id_container.rs:52:6
|
52 | impl<'a, T> std::ops::Index<Id<T>> for &'a mut IdCollection<T> {
| ^^
= note: ...so that the types are compatible:
expected std::ops::Index<id_container::Id<T>>
found std::ops::Index<id_container::Id<T>>
Why can't the compiler extend the lifetime of the get_mut? The IdCollection would then be borrowed mutably.
Note that I tried using a std::collections::HashSet<IdWrapper<T>> instead of a HashMap:
struct IdWrapper<T> {
id: Id<T>,
t: T,
}
Implementing the proper borrow etc. so I can use the Id<T> as a key.
However, HashSet doesn't offer a mutable getter (which makes sense since you don't want to mutate what's used for your hash). However in my case only part of the object should be immutable. Casting a const type to a non-const is UB so this is out of the question.
Can I achieve what I want? Do I have to use some wrapper such as a Box? Although I'd rather avoid any indirection...
EDIT
Ok I'm an idiot. First I missed the IndexMut instead of the Index, and I forgot the & when specifying the Self::Output in the signature.
Here's my full code below:
pub struct Id<T>(usize, PhantomData<T>);
impl<T> std::fmt::Display for Id<T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl<T> Hash for Id<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl<T> PartialEq for Id<T> {
fn eq(&self, o: &Self) -> bool {
self.0 == o.0
}
}
impl<T> Eq for Id<T> {}
pub struct IdCollection<T>(HashMap<Id<T>, T>);
impl<'a, T> IntoIterator for &'a IdCollection<T> {
type Item = (&'a Id<T>, &'a T);
type IntoIter = std::collections::hash_map::Iter<'a, Id<T>, T>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl<'a, T> IntoIterator for &'a mut IdCollection<T> {
type Item = (&'a Id<T>, &'a mut T);
type IntoIter = std::collections::hash_map::IterMut<'a, Id<T>, T>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter_mut()
}
}
impl<T> std::ops::Index<Id<T>> for IdCollection<T> {
type Output = T;
fn index(&self, id: Id<T>) -> &Self::Output {
self.0.get(&id).unwrap()
}
}
impl<T> std::ops::IndexMut<Id<T>> for IdCollection<T> {
fn index_mut(&mut self, id: Id<T>) -> &mut Self::Output {
self.0.get_mut(&id).unwrap()
}
}
impl<T> std::ops::Index<&Id<T>> for IdCollection<T> {
type Output = T;
fn index(&self, id: &Id<T>) -> &Self::Output {
self.0.get(id).unwrap()
}
}
impl<T> std::ops::IndexMut<&Id<T>> for IdCollection<T> {
fn index_mut(&mut self, id: &Id<T>) -> &mut Self::Output {
self.0.get_mut(id).unwrap()
}
}
If I understand correctly what you try to achieve, then I have to tell you, that it is a bit more complex than you originally thought it would be.
First of all, you have to realise, that if you like to use a HashMap then the type of the key required to be hashable and comparable. Therefore the generic type parameter T in Id<T> has to be bound to those traits in order to make Id hashable and comparable.
The second thing you need to understand is that there are two different traits to deal with the indexing operator: Index for immutable data access, and IndexMut for mutable one.
use std::{
marker::PhantomData,
collections::HashMap,
cmp::{
Eq,
PartialEq,
},
ops::{
Index,
IndexMut,
},
hash::Hash,
};
#[derive(PartialEq, Hash)]
struct Id<T>(usize, PhantomData<T>)
where T: PartialEq + Hash;
impl<T> Eq for Id<T>
where T: PartialEq + Hash
{}
struct IdCollection<T>(HashMap<Id<T>, T>)
where T: PartialEq + Hash;
impl<T> Index<Id<T>> for IdCollection<T>
where T: PartialEq + Hash
{
type Output = T;
fn index(&self, id: Id<T>) -> &Self::Output
{
self.0.get(&id).unwrap()
}
}
impl<T> IndexMut<Id<T>> for IdCollection<T>
where T: PartialEq + Hash
{
fn index_mut(&mut self, id: Id<T>) -> &mut Self::Output
{
self.0.get_mut(&id).unwrap()
}
}
fn main()
{
let mut i = IdCollection(HashMap::new());
i.0.insert(Id(12, PhantomData), 99i32);
println!("{:?}", i[Id(12, PhantomData)]);
i[Id(12, PhantomData)] = 54i32;
println!("{:?}", i[Id(12, PhantomData)]);
}
It may seem a bit surprising, but IndexMut is not designed to insert an element into the collection but to actually modify an existing one. That's the main reason why HashMap does not implement IndexMut -- and that's also the reason why the above example uses the HashMap::insert method to initially place the data. As you can see, later on, when the value is already available we can modify it via the IdCollection::index_mut.

Wrong trait chosen based on type parameter

I have a binary trait Resolve.
pub trait Resolve<RHS = Self> {
type Output;
fn resolve(self, rhs: RHS) -> Self::Output;
}
I implemented the trait for something trivial where both arguments are taken by reference (self is &'a Foo and rhs is &'b Foo):
struct Foo;
impl <'a, 'b> Resolve<&'b Foo> for &'a Foo {
type Output = Foo;
fn resolve(self, rhs: &'b Foo) -> Self::Output {
unimplemented!()
}
}
If I now write
fn main() {
let a: &Foo = &Foo;
let b = Foo;
a.resolve(&b);
}
it will compile just fine, but if I try to implement it on my struct Signal, it will not work.
pub struct Signal<'a, T> {
ps: Vec<&'a T>,
}
impl<'a, T: Resolve<&'a T, Output = T> + 'a> Signal<'a, T> {
pub fn foo(&mut self) {
let a: &T = &self.ps[0];
let b = &self.ps[1];
a.resolve(b);
}
}
error[E0507]: cannot move out of borrowed content
--> src/main.rs:25:9
|
25 | a.resolve(b);
| ^ cannot move out of borrowed content
How do I get this example working? (playground)
The trait bound on foo only says that T implements Resolve, but you try to call .resolve() on a value of type &T.
To say, instead, that references to T must implement Resolve, you need a higher-ranked trait bound:
impl<'a, T> Signal<'a, T>
where
for<'b> &'b T: Resolve<&'a T, Output = T>,
{
pub fn foo(&mut self) { ... }
}
After thinking about this I came up with a simpler solution that does not rely on HRTB.
impl<'a, T> Signal<'a, T>
where
&'a T: Resolve<&'a T, Output = T> + 'a,
{
pub fn foo(&mut self) {
let a: &T = &self.ps[0];
let b = &self.ps[1];
a.resolve(b);
}
}
This does the same, namely describe, that &T implements Resolve, but without the need of HRTB.
You have to use the where clause for this, but apart from that this is a nice and easy solution.

Trait to store structs with different generic parameters

I need to store in the same Vec instances of the same struct, but with different generic parameters. This is the struct definition:
struct Struct<'a, T: 'a> {
items: Vec<&'a T>
}
The struct has a method returning an iterator to a type that does not depend on the generic type parameter T:
impl<'a, T: 'a> Struct<'a, T> {
fn iter(&self) -> slice::Iter<&i32> {
unimplemented!()
}
}
I need to access this method for those different structs in the vector, so I've implemented this trait:
type Iter<'a> = Iterator<Item=&'a i32>;
trait Trait {
fn iter(&self) -> Box<Iter>;
}
And I've implemented the trait for Struct:
impl<'a, T: 'a> Trait for Struct<'a, T> {
fn iter(&self) -> Box<Iter> {
Box::new(self.iter())
}
}
But the compiler complains:
<anon>:21:9: 21:30 error: type mismatch resolving `<core::slice::Iter<'_, &i32> as core::iter::Iterator>::Item == &i32`:
expected &-ptr,
found i32 [E0271]
<anon>:21 Box::new(self.iter())
^~~~~~~~~~~~~~~~~~~~~
<anon>:21:9: 21:30 help: see the detailed explanation for E0271
<anon>:21:9: 21:30 note: required for the cast to the object type `core::iter::Iterator<Item=&i32> + 'static`
<anon>:21 Box::new(self.iter())
^~~~~~~~~~~~~~~~~~~~~
I've tried different possibilities for lifetime parameters in the trait, but none of them work. How can I make this work?
Rust Playground snippet
Edit
As pointed out by #MatthieuM. one problem is that the type alias is not working properly. Here's another example demonstrating this:
use std::slice;
type Iter<'a> = Iterator<Item=&'a i32>;
struct Struct<'a> { _phantom: std::marker::PhantomData<&'a i32> }
impl<'a> Struct<'a> {
fn direct<'b>(i: &'b slice::Iter<'a, i32>) -> &'b Iterator<Item=&'a i32>
{ i }
fn aliased<'b>(i: &'b slice::Iter<'a, i32>) -> &'b Iter<'a>
{ i }
}
In this example, direct compiles, but aliased not, with the error:
<anon>:12:7: 12:8 error: the type `core::slice::Iter<'a, i32>` does not fulfill the required lifetime
<anon>:12 { i }
^
note: type must outlive the static lifetime
But they seem to be the same thing. What's happening?
Problem 1 — slice::Iter<T> has an Iterator::Item of &T, thus your reference levels are mismatched. Change your method to be
fn iter(&self) -> slice::Iter<i32>
Problem 2 — Box<SomeTrait> is equivalent to Box<SomeTrait + 'static>, but your iterator does not live for the 'static lifetime. You need to explicitly bring in a lifetime:
Box<SomeTrait + 'a>
Problem 3 — I don't understand how you can create a type alias for a trait, that seems very odd. You probably don't want it anyway. Instead, create a type alias for the whole boxed version:
type IterBox<'a> = Box<Iterator<Item=&'a i32> + 'a>;
Problem 4 — Rearrange your main so that references will live long enough and add mutability:
fn main() {
let i = 3;
let v = vec![&i];
let mut traits : Vec<Box<Trait>> = Vec::new();
traits.push(Box::new(Struct{ items: v }));
}
All together:
use std::slice;
type IterBox<'a> = Box<Iterator<Item=&'a i32> + 'a>;
trait Trait {
fn iter<'a>(&'a self) -> IterBox;
}
struct Struct<'a, T: 'a> {
items: Vec<&'a T>
}
impl<'a, T: 'a> Struct<'a, T> {
fn iter(&self) -> slice::Iter<i32> {
unimplemented!()
}
}
impl<'a, T: 'a> Trait for Struct<'a, T> {
fn iter(&self) -> IterBox {
Box::new(self.iter())
}
}
fn main() {
let i = 3;
let v = vec![&i];
let mut traits: Vec<Box<Trait>> = Vec::new();
traits.push(Box::new(Struct { items: v }));
}

Resources