Michael (cc'ing rust-dev)-

On 22 May 2014, at 16:32, Michael Woerister <michaelwoeris...@posteo.net> 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`.)

_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to