0

I have a zero-copy implementation of an operation:

impl<'a, 'b> Add<&'b Key> for &'a Key {
    type Output = Key;

    fn add(self, rhs: &'b Key) -> Key {
        // ... calculate sum from given references ...
        Key::new(sum)
    }
}

I have several structs with similar properties that all implement Add with two references as input, returning a new value, i.e. &'a T: Add<&'b T, Output = T>

I'd like to write a generic function that can make use of any of these implementations, but nothing seems to satisfy the borrow checker:

pub struct FixedSet<T> {
    items: Vec<Option<T>>,
}

impl<T: Clone + PartialEq> FixedSet<T> {
...
    pub fn sum<'a>(&self) -> Option<T>
        where
            T: 'a,
            &'a T: Add<&'a T, Output=T>,
    {
        if self.items.len() == 0 {
            return None
        }
        let mut iter = self.items.iter(); //** Error **
        let mut sum = iter.next().unwrap().as_ref().unwrap().clone();
        for v in iter {
            let t = v.as_ref().unwrap();
            sum = &sum + t; // *A*
        }
        Some(sum)
    }

The error is: error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements.

I'd like to tell the compiler, "Hey, when calling add with two references to T, don't worry, the references only need to live until the return from add at A"; but I can't seem to get it right.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
CjS
  • 2,037
  • 2
  • 21
  • 29
  • Please review how to create a [MCVE] and then [edit] your question to include it. We cannot tell what crates, types, traits, fields, etc. are present in the code. For example, `Key` is undefined. Try to reproduce your error on the [Rust Playground](https://play.rust-lang.org) or in a brand new Cargo project. There are [Rust-specific MCVE tips](//stackoverflow.com/tags/rust/info) you can use to reduce your original code for posting here. – Shepmaster Mar 12 '19 at 18:44
  • TL;DR the duplicates: `pub fn sum(&self) -> Option where for<'a> &'a T: Add<&'a T, Output = T>` – Shepmaster Mar 12 '19 at 18:47
  • Your function body can also be `self.items.iter().map(|i| i.as_ref().unwrap()).fold(None, |acc, i| { acc.map_or(Some(i.clone()), |acc| Some(&acc + i)) })`; although I'm not a fan of the `unwrap`s. – Shepmaster Mar 12 '19 at 18:53
  • Or `let mut iter = self.items.iter().map(|v| v.as_ref().unwrap()); iter.next().map(|init| iter.fold(init.clone(), |acc, i| &acc + i))` – Shepmaster Mar 12 '19 at 19:04
  • Thanks @Shepmaster; I was looking for the HRTB stuff, but didn't know what to look for. Since this question is in fact a dupe, I'll just close it. – CjS Mar 12 '19 at 19:24
  • If you couldn't find those existing answers in your search, then leaving this question as a signpost to them would help someone who searched for the same query strings (which presumably you used when asking your question). – Shepmaster Mar 12 '19 at 19:27

0 Answers0