Regarding the marker types, they are somewhat awkward, and are not the
approach I originally favored. But they have some real advantages:

- Easily extensible as we add new requirements, unlike syntax.
- Easily documented.
- These bounds are only used for unsafe code, so it's not something
  ordinary users should have to stumble over.

What concerns me more is that marker types are "opt in" -- so if you
don't know that you need them, and you build a datatype founded on
unsafe code, you can get incorrect behavior. There may be some steps
we can take to mitigate that in some cases.

In any case, the use of marker types are also quite orthogonal to your
other concerns:

> This also makes the intent much more clear.   Currently, one would have to
> dig into the definition of MutItems<'a,T> to figure out that the lifetime
> parameter 'a is used to create a dummy borrow field into the vector, so
> that the whole iterator is then treated as a mutable borrow.   This feels
> very convoluted, if you ask me.

I disagree -- I think treating lifetime and type parameters uniformly
feels cleaner than permitting lifetime bounds to appear in random
places. Presumably `'a Foo<T>` would be syntactic sugar for `Foo<'a, T>`?
There's an obvious ambiguity here with `&'a T`.

> On a slightly different note, is there a strong reason for having to name
> lifetime parameters explicitly?   Could we simply re-use actual parameter
> names prefixed with ' as their lifetimes?

It is plausible we could say that a lifetime parameter name that is
the same as a local variable binding whose type is a borrowed pointer
refers to the lifetime of that borrowed pointer. To me, it feels like
a rather ad hoc rule, though I can see it would sometimes be convenient.

The current rules are intended to showcase how lifetime parameters work
precisely like type parameters. In other words, we write:

    fn copy<T>(t: T) -> T;

we do not write:

    fn copy(t) -> t;

In the same way, we identify and declare lifetime parameters.

Note that lifetime parameters do not have a natural one-to-one
relationship with variables. It's certainly possible (and reasonable)
to declare a function like:

    fn foo<'a, 'b, 'c>(x: &'a Foo<'b, 'c>)

In which case, the meaning of `'x` is pretty unclear to me.

> The above could then be reduced to this:
> 
>     pub trait MutableVector<T> {
>         fn mut_iter(self) -> 'self MutItems<T>;
>         ...
>     }
> 
> This used to be valid syntax, btw, though it worked because 'self lifetime
> was special, IIRC.

Writing `'self` was valid syntax, but it didn't have the meaning you
are proposing. Which is one of the reasons we removed it.



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

Reply via email to