Some discussion has sprouted on reddit: http://www.reddit.com/r/rust/comments/1j5vbn/rustdev_rfc_removing_t/
On Sat, Jul 27, 2013 at 4:51 PM, Gábor Lehel <[email protected]> wrote: > Spurred by https://github.com/mozilla/rust/issues/7694 I was thinking > about the differences between `*` and `&` and the reason both need to > exist. > > As far as I can tell the differences boil down to: > > - The compiler makes no attempt to enforce any invariants for `*T` > > Meaning that, in an interesting duality-ish: > > - Creating `*T` out of `&T` (or anything else) and manipulating it in > any which way is always safe > - Dereferencing `*T` is unsafe > - Creating `&T` out of `*T` is unsafe > - Dereferencing `&T` (and whatever else the language lets you do with it) > is safe > > Behind it is proof obligations. `*T` has no implied invariants and > therefore doesn't require proof of anything, while as long as you stick to > `&T`, safety is proved by the compiler. It's at the boundary where the > burden is on the programmer: to assert (with an `unsafe` block) that the > invariants required for dereferencing `*T` and/or converting it to `&T` > really do hold. > > The use case for `*T` is operations which are not known to respect > invariants: notably foreign functions, also e.g. pointer arithmetic. > > The invariants required of `&T` but not `*T` are: > > 1. The pointer is not null > 2. The pointed-to object is of type `T` > 3. The pointed-to object is alive and initialized > 4. (Im)mutability and aliasing related invariants > > The latter three of which are guaranteed for the lifetime associated with > the pointer. > > Now crazy ideas: > > We can waive the first invariant by using `Option`. If we could guarantee > in the language that `None : Option<&T>` is represented as a null pointer, > then I see no reason whatsoever to keep allowing implicit nullability. It's > binary compatible with C, so (except where can't-be-null is known) C > interfaces would simply use Option. It forces proper attention to nulls, > and I don't actually see any drawback. > > We can waive the other invariants by taking advantage of the fact that > they're predicated on a lifetime, to introduce a new special lifetime > `'unsafe`, which is the inverse of `'static`. Where `'static` is always > known to be alive, `'unsafe` never is. (So `'static` is top and `'unsafe` > is bottom.) Therefore converting `&'a T` to `&'unsafe T` is always allowed, > while if you have an `&'unsafe T` and want to convert it to a pointer with > a longer lifetime and dereference it, you have to use `unsafe { }`, just > as with `*T`. Functions parameterized over lifetime variables would > continue to require that the lifetime encompass the duration of the call, > so if you want to allow `&'unsafe T` as an argument, you have to write that > explicitly (again as with `*T`). > > One question is whether you might want to waive 2-4. with finer > granularity: > > - You could waive only 2. by using `&()`. It's not clear to me if it makes > sense to talk about a definitely-live-and-initialized(-and-immutable) value > of unknown type, but if there's a use case for it, it can be satisfied. > > - I don't think it makes sense to waive only 3.: you can't say a dead or > uninitialized value is of type T, because it could be *anything* (which is > why `'unsafe` above, conceptually most closely tied to 3., also waives 2. > and 4.). > > - It might make sense to waive only 4.: you might care only that a value > is alive and of type T, not whether anyone else is mutating it: this is > `&const T` (which is hoped to be removed). You might also want to mutate it > while not caring whether anyone else is also reading or writing: there's no > separate mutability qualifier for this, a use case might be e.g. atomic > operations. But even in the absence of any special features, these can > still be satisfied by using `&'unsafe [mut] T`, which is an > overapproximation, just as with `*[mut] T` today. > > (Corresponding to the separate invariants, it might make sense to have > separate functions for unsafely manipulating the pointed-to type, lifetime, > and mutability of a borrowed pointer, instead of just the catch-all > `transmute()`, similarly to C++.) > > Summary: > > I think we could replace `*` pointers with a combination of guaranteeing > the null pointer optimization for `Option` (kinda like TCO) and introducing > a new special lifetime `'unsafe`. This would retain the desirable > properties of the current system, while being superior in other ways, such > as orthogonality. Whether and how to waive aliasing and mutability related > invariants separately from the others might need more thinking, but is > independent. > > Thoughts? > > -- > Your ship was destroyed in a monadic eruption. > -- Your ship was destroyed in a monadic eruption.
_______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
