On 22.05.2014 17:54, Felix S. Klock II wrote:
Michael (cc'ing rust-dev)-

On 22 May 2014, at 16:32, Michael Woerister <[email protected]> wrote:

Lately I've been thinking that it might be nice if one could omit the lifetimes 
from the list of generic parameters, as in:

fn foo<T>(x: &'a T, y: &'b MyStruct) -> (&'b int, &'a uint)

instead of

fn foo<'a, 'b, T>(x: &'a T, y: &'b MyStruct) -> (&'b int, &'a uint)

Especially for otherwise non-generic functions, having to explicitly list 
lifetimes seems a bit redundant, as they are unambiguously defined in the 
function signature anyway (as opposed to type parameters, which don't have the 
special `'` marker).
Note that this is not true in the general case.  Consider e.g. methods with an 
type impl or a trait impl: in that scenario, one could bind lifetimes on the 
method itself, or in the type/trait being implemented.  This distinction 
matters (in terms of what limits it imposes on the clients of those 
types/traits).

(I provide a concrete example after my signature.)

There are other changes one could make to still accommodate a change like you 
suggest in the general case, such as inferring some binding site (e.g. the 
nearest one) if a lifetime is otherwise found to be unbound.  But I personally 
do not think such changes improve the character of the language (IMHO); I'd 
rather have a straight-forward rule that one applies in every context.

Cheers,
-Felix

Concrete Example:

The variants below are quite different.

     #[deriving(Show)]
     struct S<'a> {
         p: &'a int
     }

     impl<'a> S<'a> {
         #[cfg(variant1)]
         fn foo(&mut self, arg: &'a int) -> &'a int {
             let old = self.p;
             self.p = arg;
             old
         }

         #[cfg(variant2)]
         fn foo<'a>(&mut self, arg: &'a int) -> &'a int {
             let old = self.p;
             self.p = arg;
             old
         }

         #[cfg(variant3)]
         fn foo<'a>(&mut self, arg: &'a int) -> &'a int {
             arg
         }

         #[cfg(variant4)]
         fn foo<'a>(&mut self, arg: &'a int) -> &'a int {
             self.p
         }

         #[cfg(variant5)]
         fn foo<'a>(&self, arg: &'a int) -> &'a int {
             self.p
         }

         #[cfg(variant6)]
         fn foo<'a>(&'a self, arg: &'a int) -> &'a int {
             let _ = arg;
             self.p
         }
     }

     #[allow(unused_mut)]
     fn main() {
         let x = 3;
         let mut s = S{ p: &x };
         let y = 4;
         println!("begin: {:?}", s);
         let z = s.foo(&y);
         println!("later: {:?} z: {:?}", s, z);
     }

Half of them do not compile (for differing reasons).  Variants 1, 3, and 6 do 
run (and each produces a different output), but the interesting points come 
from understanding why the other cases do not compile.

(FYI: It is probably easier to talk about the example if you first alpha-rename 
the method-bound lifetimes to something other than `'a`.)


Thanks for the detailed response, Felix. You are right, I didn't think about nested cases. It *would* still be possible to leave the lifetime parameters out of the list, but the proposition loses some of its allure. I'm not sure, though, if the outcome would be that bad. Nesting is not arbitrarily deep in practice and assuming that unbound variables belong to their nearest enclosing scope, as you suggest, seems like a reasonable idea from a program-readability perspective.

I find variant #6 from your example rather interesting! At first glance, it seems that it shouldn't be possible to relate the lifetimes of `self` (lets call it 'b) and `self.p` (let's stay with 'a) in this case. Does the borrow checker infer a sub-typing relationship between the two lifetimes (i.e. 'a <: 'b)? It would make sense to say that a reference contained in some aggregate will always live at least as long as any reference to the aggregate, iff it is guaranteed that the contained reference always outlives the aggregate... as in:

L(&A) < L(A) && L(A) < L(A.x)   ===> L(&A) < L(A.x)

I think, I just learned something new here :)

Cheers!
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to