Reporting progress using a Follower My goal is to implement a function that accepts a Follower object that will be used to report progress through a complex function (a depth-first traversal of a graph). Here's my attempt:

pub trait Follower&lt;'a, N&gt; {
    fn root(&amp;mut self, node: &amp;'a N);
}

pub fn depth_first&lt;'a, N&gt;(
    node: &amp;'a N, follower: &amp;mut dyn Follower&lt;'a, N&gt;
) {
    follower.root(node);

    // TODO
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fmt::Display;

    struct DebugFollower&lt;'a, N&gt; {
        nodes: Vec&lt;&amp;'a N&gt;
    }

    impl&lt;'a, N: Display&gt; DebugFollower&lt;'a, N&gt; {
        fn new () -&gt; Self {
            DebugFollower { nodes: vec![ ] }
        }

        fn to_string(&amp;self) -&gt; String {
            self.nodes.iter().map(ToString::to_string).collect()
        }
    }

    impl&lt;'a, N&gt; Follower&lt;'a, N&gt; for DebugFollower&lt;'a, N&gt; {
        fn root(&amp;mut self, item: &amp;'a N) {
            self.nodes.push(item);
        }
    }

    #[test]
    fn walks_p1() {
        let mut follower = DebugFollower::new();

        depth_first(&amp;0, &amp;mut follower);

        assert_eq!(follower.to_string(), "0");
    }
}


The code compiles and performs as expected. However, I suspect that, in trying to silence the many compile errors I encountered, I may have added unnecessary lifetime parameters. Previous experience has shown me that it's very easy to get into a situation wherein so many useless parameters have been added that removing them one at a time isn't possible. Still, I have tried to do that and can't find any lifetime parameters that can be removed.

In particular, I'm suspicious of the lifetime parameter on Follower, which appears to leak implementation details from DebugFollower. For example, removing the nodes property from DebugFollower, and updating the rest of the code, Follower no longer needs a lifetime parameter. 

Does this example follow idiomatic Rust use of lifetime parameters? If not, how can I improve the use of lifetime parameters here?
You can get rid of the lifetimes completely, just replace every instance of:

&amp;'a N


with just:

N


See Playground

But why? Well, in your current code N is inferred to be i32. However, with my suggested changes N will be inferred to be &amp;'a i32. If you allow Rust to infer the reference it will also infer the correct lifetime for you.

But does this, as you ask, leak implementation details of DebugFollower? Not from a Rust perspective. In Rust, ownership details are very much part of the interface and not just an implementation detail. The key issue is that the Follower trait has to specify how long the references will be valid so that DebugFollower knows how long it is allowed to store those references.