Troubles with lifetimes and associated types


#1

I’m attempting to create a chain of associated types containing references, but haven’t been able to figure out how to structure the lifetimes.

I have some example code posted on GitHub which demonstrates the error that I’m running into.

An excerpt:

struct Encoder<'a, S: for<'b> Sink <'b> + 'a> { // does this mean that 'b is longer that 'a? 
    sink: &'a S,
}

impl<'a, S: for<'b> Sink<'b> + 'a> Encoder<'a, S> {
    fn encode(&self) {
        let req = <S::Response as Response>::Request::new("test");
        let resp = S::Response::new("test", &req);
        self.sink.write(&resp)
    }
 // ^ `req` dropped here while still borrowed
}

I’m suspecting the error is being cause by lifetime 'b being constrained to being longer than 'a. How can I tie the lifetime to the encode method instead while keeping the S: Sink constraint on Encoder?


#2

I think this might be a case where you’d want associated type constructors, so Sink would have no lifetime itself, just its associated type, something like:

pub trait Sink {
    type Response<'a>: Response<'a>;
    fn write<'a>(&self, &Self::Response<'a>);
}

#3

This looks like Response::new is eating borrows. Here’s a simplified example:

https://play.rust-lang.org/?gist=37394c95759e9980410acdea2e32087a&version=nightly&backtrace=0

The fundamental issue here is that the compiler doesn’t know that a function taking a &'a S where S: Trait<'a> doesn’t have the ability to store a part of the borrow into the parameter itself. This combines with the fact the compiler also doesn’t know whether S implements Drop, which would make it so that the value cannot be borrowed at the point where it goes out of scope. Basically, in this super generic context, you need some way to encode this as &'a S where S: Trait<'b> instead, but without associated type constructors (as mentioned by cuviper), I can’t see a way to accomplish this.


#4

This it the conclusion I had come to as well and came to post, but you beat me to it! :slight_smile:


#5

Thanks, all. Associated type constructors sounds like exactly what I need. I’ll need to take this problem from another angle.

Looking forward to more HKT features in Rust!