[rust-dev] Simplifying lifetime expression

Steven Blenkinsop steven099 at gmail.com
Tue Apr 23 12:10:49 PDT 2013

One potential default that might be useful/not terrible, though I can't say
I've thought of all the possible implications, is for the lifetimes in the
return value to default to the intersection of the lifetimes in the
parameters, thereby allowing anything borrowed by one of the parameters to
be returned by the function by default.

On Tuesday, April 23, 2013, Steven Blenkinsop wrote:

> A fresh lifetime is a better default behaviour.  For example,
>     fn F(x: &mut T)
> could be either
>     fn A<'a>(x: &'a mut T<'a>)
> or
>     fn B<'a, 'b>(x: &'a mut T<'b>)
> In A, it's possible for any borrow with lifetime 'a to escape via the
> mutable state in x, including the borrow into x itself. This makes it so
> you can't call A with any `&mut T` that has a shorter lifetime than the
> contents of the T, and the borrow into A will be alive and inaccessible for
> the remainder of the lifetime of the contents of the T. B is almost
> certainly what people will want when they write F.
> On Tuesday, April 23, 2013, Paulo Sérgio Almeida wrote:
>> Ok. Suppose the current syntax is frozen. But I talked about two things:
>> syntax for explicit lifetimes (mainly point 3, altough a bit also in points
>> 1 and 2) and defaults for when no explicit (named) lifetimes are used.
>> Even if no syntax change is made, for the cases when named lifetimes are
>> used, what I find specially painful is the default rule when no explicit
>> lifetimes are used:
>> "an implicit fresh lifetime for each parameter and result".
>> This rule, specially when a result is involved, which is exactly one of
>> the cases when stating lifetime is needed, seems to make little sense, and
>> will force named lifetimes to be used in many cases, causing noise and
>> distraction and decreasing legibility.
>> In what way is the default that I propose, which basically is:
>> "one implicit fresh lifetime for each type parameter and another for all
>> the remainder parameter types"
>> confusing or a possible source of obscurity? I find it quite natural
>> that, e.g., if I am returning a borrowed reference (not a copy, not an
>> owned, not a @) of type T and I have received one or more borrowed
>> references to T, i.e.:
>> fn f<T>(p1: &T, p2: &T, ...) -> &T  { ... }
>> the *natural* thing to expect is that the result comes from one of the T
>> that I received as parameters, and the default that I propose is not
>> obscure at all, but makes the code cristal clear. I find having to write
>> fn f<'r, T>(p1: &'r T, p2: &'r T, ...) -> &'r T  { ... }
>> because of the current defaults, needlessly painful and distracting. Is
>> the current default less obscure? Will it cause less surprise? Or it is the
>> other way around ...
>> Regards,
>> Paulo
>> On 4/23/13 4:11 PM, Niko Matsakis wrote:
>>> Thanks for your proposal. We've been through a number of rounds with the
>>> lifetime syntax, including an earlier scheme that was quite similar to
>>> what you propose in some regards (there was a single anonymous lifetime
>>> parameter that was used whenever you wrote `&T`, which meant that yes
>>> you often did not need to use explicit lifetime parameter names).
>>> However, we found that this was ultimately more confusing to people than
>>> helpful. One of the goals of the current syntax was to make the
>>> mechanism of named lifetimes more explicit and thus more clear to the
>>> reader. Smarter defaults have the disadvantage that they often obscure
>>> the underlying system, making it harder to learn what's really going on.
>>> In practice,named lifetimes don't seem to be that common, at least for
>>> me. We should do some numerical analysis, but I've found subjectively
>>> that most functions simply consume data and do not return pointers. This
>>> is particularly true for "non-library" code, and even more true with
>>> judicious use of `@` pointers (it is often not worth the trouble to
>>> avoid the GC; it can make life much easier, that's what it's there for).
>>> So in summary I do not think it likely we will change the current syntax.
>>> Niko
>>> On Mon, Apr 22, 2013 at 12:21 PM, Paulo Sérgio Almeida <psa at di.uminho.pt
>>> <mailto:psa at di.uminho.pt>> wrote:
>>>     Hi all,
>>>     (My first post here.)
>>>     First, congrats for what you are trying to achieve with Rust. I
>>>     arrived very late to the party, and so I am not sure that what I
>>>     will say can be of use. But as I understand, lifetimes is one of
>>>     those things that are not completely solidified, and anyway, better
>>>     late than never.
>>>     Looking at some code, expressing lifetimes of borrowed references is
>>>     one of those things that is somewhat bewildering, making the code
>>>     somewhat noisy. I think it can be improved through a better choice
>>>     of defaults and a slight change in explicit lifetimes.
>>>     The main thing I think is "wrong" is the defaults for function
>>>     parameters. From the tutorial: "the compiler simply creates a fresh
>>>     name for the lifetime automatically: that is, the lifetime name is
>>>     guaranteed to refer to a distinct lifetime from the lifetimes of all
>>>     other parameters."
>>>     This default is not very useful. For example, it is wrong basically
>>>     everytime we want to return a borrowed pointer (unless, for a global
>>>     variable?). The more common case is returning something with the
>>>     same lifetime as some parameter. In many cases we don't need to
>>>     distinguish parameters, and specify which we are returning, in
>>>     others we want to split parameters in two equivalence classes, the
>>>     one from which we are returning, and everything else.
>>>     When type parameters are involved, a return type typically says
>>>     where the result comes from most of the times. Again, the default
>>>     should be different. E.g., when we are returning a borrowed
>>>     reference to a "key" of type parameter K, the default should be
>>>     "other things also of type K in parameters".
>>>     Finally, with better defaults, in the remaining cases where we need
>>>     to explicitly express lifetimes, having to "invent" identifiers is a
>>>     nuisance. Also the space which must be used between the lifetime
>>>     identifier and the type is too distracting and makes it cumbersome
>>>     (for humans) to "parse" the type of some identifier.
>>>     I have been thinking about this and have the following proposal. (Of
>>>     course there may be inumerous things that must have escaped me, but
>>>     here it goes anyway.)
>>>     ---
>>>     Regarding types for borrowed references in function parameters or
>>>     result, and type parameters:
>>>     1) each type-parameter has an associated implicit lifetime, which by
>>>     default is different from the lifetimes of other type-parameters or
>>>     normal function parameter types, but it can be qualified in each
>>>     declaration or use with an explicit lifetime;
>>>     2) function parameter types or return type that are not type
>>>     parameters have all the same implicit lifetime by default, but they
>>>     can be qualified explicitly with some lifetime.
>>>     3) explicit lifetimes are written identifier' instead of
>>>     'identifier; a null identifier is allowed, as in &'T, to qualify a
>>>     reference &T with lifetime '.
>>>     ---
>>>     (Another useful possibility would be allowing several ' at the end,
>>>     allowing e.g., &T, &'T, &''T as borrowed references to the same type
>>>     but with different lifetimes. In practice, a single ' plus 1) and 2)
>>>     will cover "99%" of cases. We         Rust-dev at mozilla.org <mailto:
>>> Rust-dev at mozilla.org>
>>>     https://mail.mozilla.org/**listinfo/rust-dev<https://mail.mozilla.org/listinfo/rust-dev>
>> ______________________________**_________________
>> Rust-dev mailing list
>> Rust-dev at mozilla.org
>> https://mail.mozilla.org/**listinfo/rust-dev<https://mail.mozilla.org/listinfo/rust-dev>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20130423/1241166c/attachment.html>

More information about the Rust-dev mailing list