Returning a reference to data from within a value with a larger lifetime than the local scope fails because the returned value references a local closure somehow... How?

I have some code that looks like this:

/// A kludge to satisfy the borrow checker on `RefCell` borrows.
/// We will never borrow the data we use this macro with mutably at any point,
/// and so it will have no reason to panic.
macro_rules! do_unchecked_borrow {
    ($cell: expr) => {
        unsafe { $cell.try_borrow_unguarded().unwrap() }
    }
}

// ...

    // Handle = Rc<Node>
    fn find_elements_by_attr_with_predicate<P>(&'a self, predicate: &'a P) -> Vec<&'a Handle>
    where
        P: Fn(&'a Attribute) -> bool,
    {

        let mut res = vec![];

        match self.data {
            NodeData::Document => {
                for it in do_unchecked_borrow!(self.children).as_slice() {
                    res.append(&mut it.find_elements_by_attr_with_predicate(predicate))
                }
            }
            NodeData::Element { ref attrs, .. } => {
                if do_unchecked_borrow!(attrs).iter().any(|it| predicate(it)) {
                    res.push(self)
                } else {
                    for it in do_unchecked_borrow!(self.children).as_slice() {
                        res.append(&mut it.find_elements_by_attr_with_predicate(predicate))
                    }
                }
            }
            _ => {}

        }

        res
    }

    // The problem function.
    fn find_element_by_attr_value(&'a self, value: &'a str) -> Option<&'a Handle> {
        // pred is only used within this function.
        let pred = move |attr: &Attribute| attr.value.as_ref() == value;
        let a: Vec<&Rc<Node>> = self.find_elements_by_attr_with_predicate(&pred);  
        let b: Option<&&Rc<Node>> = a.get(0);
        let c: Option<&Rc<Node>> = b.copied();
        c // Compiler thinks c borrows pred somehow...
    }

self is of type Handle (a.k.a Rc<Node>).
The Vec assigned to a holds references to data held by self. I don't believe there are any references to temporary data that would be invalidated when returning from any of these functions, but the compiler disagrees:

error[E0515]: cannot return value referencing local variable `pred`
   --> endpoints/src/lib.rs:295:9
    |
295 |           self.find_elements_by_attr_with_predicate(&pred)
    |           ^                                         ----- `pred` is borrowed here
    |  _________|
    | |
296 | |         .get(0)
297 | |         .copied()
    | |_________________^ returns a value referencing data owned by the current function

I'm having a hard time understanding how pred is borrowed by whatever is held in a, b or c. What could I do to resolve this confusion?

Thanks for any help!

I’m pretty sure that this declaration needs two differently-named lifetimes, so that the life of predicate doesn’t limit the life of the return value:

1 Like

That fixed it. Here's the modified version I made:

fn find_elements_by_attr_with_predicate<P>(&'a self, predicate: &'b P) -> Vec<&'a Handle>
    where
        P: Fn(&'b Attribute) -> bool, 'a: 'b

Thank you for the help!

1 Like

Generally you should not take references to closures in the first place. Just take the closure by value.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.