Stream: t-lang/wg-unsafe-code-guidelines

Topic: overlapping mutable slices


Jake Goulding (Feb 11 2019 at 16:09, on Zulip):

I know that two mutable references to the same value are insta-UB, but do overlapping references have the same behavior?

[1, 2, 3]
 ^^^^----- slice_0
    ^^^^-- slice_1
RalfJ (Feb 11 2019 at 16:22, on Zulip):

yes

RalfJ (Feb 11 2019 at 16:22, on Zulip):

"aliasing" is not "equal pointers", it is "overlapping ranges"

RalfJ (Feb 11 2019 at 16:22, on Zulip):

so actually two &mut () to the same value are fine

Jake Goulding (Feb 11 2019 at 16:24, on Zulip):

two &mut () to the same value

I'm not following. How do you have two &mut () to a value unless the value is itself or contains a ()?

Cem Karan (Feb 11 2019 at 16:50, on Zulip):

I think what @RalfJ is saying is that aliasing only occurs when the thing being referenced is a non-empty set. Since () is always empty, aliasing cannot occur. If this is so, does this mean that references to PhantomData instances are also OK? What about anything else that is empty?

Jake Goulding (Feb 11 2019 at 16:57, on Zulip):

[T; 0] comes to mind.

Jake Goulding (Feb 11 2019 at 16:57, on Zulip):

I suppose that the statement "you cannot alias something that takes zero size" seems pretty reasonable

Cem Karan (Feb 11 2019 at 18:52, on Zulip):

What about ownership? AFAIK, you can't read/write a zero-sized type (someone check me on this, I could be wrong), but the objects are still referenced, so, will there be lifetime problems?

RalfJ (Feb 11 2019 at 20:39, on Zulip):

I don't follow. "lifetime problem"? sounds like you are talking about references, but you started out with "ownership"?

RalfJ (Feb 11 2019 at 20:40, on Zulip):

we are specifically talking about references here, and since aliasing is defined as pointing to overlapping ranges, references to ZST cannot really alias

Cem Karan (Feb 11 2019 at 20:56, on Zulip):

I'm sorry, I was being really, really unclear about this. Consider the following code:

fn main() {
    let mut d: &[u64];
    {
        let mut a: [u64; 3] = [1, 2, 3];
        d = &a[1..1];
    }
    println!("d = {:?}", d);
}

Today, this code will not compile because a doesn't live long enough for d. But d is empty; why can't this code compile? After all, if we can't read or write to this, then does it really matter? If it's like the mathematical concept of the empty set, then we can treat all empty references as if they are the same object (IIRC, there is one empty set in the universe; all empty sets alias to it). If it isn't like the mathematical concept of the empty set, then there is additional information there, and the scoping rules are correct. My comment about the 'lifetime problem' included this problem.

rkruppe (Feb 11 2019 at 21:06, on Zulip):

One thing to keep in mind is that the rules the compiler enforces for safe Rust are only a conservative approximation of the rules governing UB -- safe programs must be UB-free, but not every UB-free program can be written entirely in safe Rust

RalfJ (Feb 11 2019 at 21:09, on Zulip):

@Cem Karan I see. I am not sure I have a good answer for your particular example, but notice that I spoke only about aliasing in particular.

RalfJ (Feb 11 2019 at 21:09, on Zulip):

to have an &mut T, you must not just make sure that there is no aliasing reference, you must also make sure that it points to a T

Cem Karan (Feb 11 2019 at 21:10, on Zulip):

@RalfJ You're right, unfortunately for me, my brain tends to skip around a lot, which is how this came to mind.

RalfJ (Feb 11 2019 at 21:10, on Zulip):

a library can use a zero-sized type as a kind of "token" that indicates a permission or some such thing, and creating such references "out of thin air" would certainly not be allowed

RalfJ (Feb 11 2019 at 21:11, on Zulip):

but for your example, I agree with @rkruppe -- it's the compiler being conservative, mostly. (and also because maintaining pointer equality is nice.) the compiler does not reason about array indices.

RalfJ (Feb 11 2019 at 21:11, on Zulip):

e.g., you cannot do let x = &mut a[1]; let y = &mut a[2]; *x = 5; even though x and y definitely do not alias

Cem Karan (Feb 11 2019 at 21:12, on Zulip):

@rkruppe I'm glad that the rules are a conservative approximation. I was thinking about other, weirder cases on the way to work yesterday, and I'm not sure how they can be handled, or if they are forever going to be UB.

RalfJ (Feb 11 2019 at 21:13, on Zulip):

re: the empty set, a reference to a ZST certainly has some information -- namely, it points to a particular address in memory. while it does not alias with anything, that address is still observable and can be significant. we actually fixed iterators over slices of ZSTs to make sure they use a consistent address.

RalfJ (Feb 11 2019 at 21:14, on Zulip):

the one thing that is empty here is the set of addresses "covered" by the reference. but for that, the fact that all empty sets are equal bears no significance.

Cem Karan (Feb 11 2019 at 21:20, on Zulip):

Once again, I was being unclear. You're right that the set of addresses covered by the reference is empty, but what I failed to talk more about was exactly what you pointed out; that the existence of the reference could be important. In which case the 'set of interesting stuff' is not empty, even on such a reference. If it were empty, then it could be disposed of.

RalfJ (Feb 11 2019 at 21:22, on Zulip):

more importantly, it could be created arbitrarily

RalfJ (Feb 11 2019 at 21:22, on Zulip):

(everything in Rust can be disposed of, see mem::forget)

Cem Karan (Feb 11 2019 at 21:23, on Zulip):

Not the kind of 'disposed of' I was thinking about; I meant that the compiler could optimize it away.

RalfJ (Feb 11 2019 at 21:23, on Zulip):

ah, yes

RalfJ (Feb 11 2019 at 21:23, on Zulip):

though the compiler can and will optimize many interesting things away :)

Cem Karan (Feb 11 2019 at 21:24, on Zulip):

True, that! :)

RalfJ (Feb 11 2019 at 21:24, on Zulip):

all this ownership discipline and lifetimes is entirely a compile-time fiction, after all. it is very interesting, and yet entirely "disposed of". ;)

Cem Karan (Feb 11 2019 at 21:24, on Zulip):

That is true.

Last update: Nov 20 2019 at 12:45UTC