Can you clarify the syntax for function types with lifetime parameters? I
saw this in the meeting transcript:

&fn<'a>(f: &fn(&'a T))
> &fn(f: &fn<'a>(&'a T))


I think I've filled in blanks that were left correctly. I'm guessing the
that the first case forces the lifetime 'a to be known when you call the
function, and the second case allows the lifetime 'a to be determined
inside the body of the function as needed on each call to f. I'm pretty
sure that the <'a> in both cases is new syntax, since I don't think you can
put type parameters on function values. Is this correct?

On Tuesday, February 5, 2013, Niko Matsakis wrote:

>
>
> Graydon Hoare wrote:
>
> # Lifetime parameters and impls
>
> ...
>
> This is *slightly* different than today.  This is because, today,
> `&self` is equivalent to a self type of `&'b Iterator<'b, T>` rather
> than using a fresh lifetime (like `&'a Iterator<'a, T>`).  The current
> system causes various issues in real-life examples, including this
> specific iterator example.
>
> I do not entirely understand what the failure mode is. Are you saying
> that today, an omitted lifetime parameter in an impl method signature
> gets its default provided from the underlying type's lifetime parameter,
> whereas in the new regime it will get a fresh parameter provided?
>
>
> More or less, yes.
>
>  If so, I don't know the exact way it goes wrong (or really see it in the
> example here), but it works better, I trust you know why, that's fine.
>
>
> This is indeed what I mean and yes it can go wrong.  Let me spell out what
> happens with the Iterator example, it's a bit involved and took me some
> time to fully appreciate. To begin, today you have the following
> annotations on the `next()` method, effectively:
>
>     impl<'b, T> Iterator<'b, T> {
>         fn next<T>(&'b mut self) -> Option<&'b T> { /* same as before */ }
>     }
>
> As you can see, both the lifetime of the `&mut self` pointer and the
> lifetime of the contents are `'b`.  Now let's have an example of some code
> that invokes `next()`.  This is the standard `find()` function for vectors,
> expressed with an iterator.  It iterates down the list and returns the
> first item that matches some predicate `pred`.  I have included all
> possible annotations and made all borrows explicit.  Key lines are numbered
> in comments.
>
>     fn find(v: &'lt [T], pred: &fn(&'lt T) -> bool) -> Option<&'lt T> {
>         let iterator = Iterator(v);
>         loop {
>             let result: Option<&'lt T> =    /* [1] */
>                 (&'lt mut iterator).next(); /* [2] */
>             match result {
>                 None => { return None; }
>                 Some(r) => {
>                     if pred(r) {
>                         return Some(r); /* [3] */
>                     } else {
>                         return None;
>                     }
>                 }
>             }
>         }
>     }
>
> The lifetime of the input vector is 'lt.  The signature promises to invoke
> the predicate function with data in the vector (and hence with the same
> lifetime) and to return an element of the vector (and hence with the same
> lifetime).  The first important point is that, when we call `next()`, the
> lifetime of the resulting pointer must also be 'lt (as indicated in the
> type annotation [1]).  This is because we are going to be returning this
> result if it matches the predicate ([3]).  Now, because the lifetime of the
> pointer to the iterator and the lifetime of the iteratee are specified as
> the same ('b), this means that the lifetime of the borrow must be the same
> [2].
>
> So, as a result of the above rules, the iterator is borrowed mutably for
> the full lifetime 'lt.  This makes the borrow checker unhappy because it is
> only supposed to allow one mutable alias to iterator at a time, but the
> scope of the first mutable borrow outlives the enclosing loop (in fact, it
> outlives the entire `find()` function), and thus it seems to the borrow
> checker that you are creating new mutable aliases while the old ones still
> exist.  Thus you get errors.  These problems go away when you don't
> artificially conflate the lifetime attached to the `&self` pointer with the
> lifetime of the stuff it points at.
>
> In general, I prefer this model anyhow because it treats `self` more like
> the other parameters to the function, which I think is somewhat less
> surprising and well simplify the specification and implementation.
>
> Compatible and future-concern, defer.
>
>
> Yes, adding label syntax is compatible and not something I particularly
> want to nail down now.  The main reason that I mention it is that, with
> regard to pcwalton's desire for backwards-compatible language support, I
> would rather not be locked in to the current labeled loop system we have
> now.
>
>
> regards,
> Niko
>
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to