6

Implementation of GATs outlives lint by jackh726 · Pull Request #89970 · rust-la...

 2 years ago
source link: https://github.com/rust-lang/rust/pull/89970
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Copy link

Contributor

jackh726 commented on Oct 17

See #87479 for background. Closes #87479

The basic premise of this lint/error is to require the user to write where clauses on a GAT when those bounds can be implied or proven from any function on the trait returning that GAT.

Intuitive Explanation (Attempt)

Let's take this trait definition as an example:

trait Iterable {
    type Item<'x>;
    fn iter<'a>(&'a self) -> Self::Item<'a>;
}

Let's focus on the iter function. The first thing to realize is that we know that Self: 'a because of &'a self. If an impl wants Self::Item to contain any data with references, then those references must be derived from &'a self. Thus, they must live only as long as 'a. Furthermore, because of the Self: 'a implied bound, they must live only as long as Self. Since it's 'a is used in place of 'x, it is reasonable to assume that any value of Self::Item<'x>, and thus 'x, will only be able to live as long as Self. Therefore, we require this bound on Item in the trait.

As another example:

trait Deserializer<T> {
    type Out<'x>;
    fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a>;
}

The intuition is similar here, except rather than a Self: 'a implied bound, we have a T: 'a implied bound. Thus, the data on Self::Out<'a> is derived from &'a T, and thus it is reasonable to expect that the lifetime 'x will always be less than T.

Implementation Algorithm

  • Given a GAT <P0 as Trait<P1..Pi>>::G<Pi...Pn> declared as trait T<A1..Ai> for A0 { type G<Ai...An>; } used in return type of one associated function F
  • Given env E (including implied bounds) for F
  • For each lifetime parameter 'a in P0...Pn:
    • For each other type parameter Pi != 'a in P0...Pn: // FIXME: this include of lifetime parameters too
      • If E => (P: 'a):
        • Require where clause Ai: 'a

Follow-up questions

  • What should we do when we don't pass params exactly?
    For this example:
trait Des {
    type Out<'x, D>;
    fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, Wrap<T>>;
}

Should we be requiring a D: 'x clause? We pass Wrap<T> as D and 'z as 'x, and should be able to prove that Wrap<T>: 'z.

r? @nikomatsakis


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK