← Back to context

Comment by amluto

5 hours ago

In my mind, a no-access reference would have exactly the same lifetime rules (except for the exclusivity part) as any other reference. And they'd have the same size and lifetime rules.

Unsafe Rust could promote a no-access reference to a shared or a mutable reference, and the unsafe code would be responsible for not violating exclusivity rules but would have a guarantee that the referent actually exists. Using unsafe code to create a no-access reference to a nonexistent object or to a misaligned object would be UB.

Safe code could convert the other way:

    let a: &mut u32 = ...;
    let b: &noaccess u32 = a;
    let c: &u32 = ...;
    let d: &noaccess u32 = c;

This is not an entirely serious proposal.

Under NLL, reference lifetime is defined by the places where the reference is used, and noaccess types can't be used. So then reference lifetime has to devolve to the spans where the reference is live, which is only defined lexically.

So for example:

    let mut data = vec!['a', 'b', 'c'];
    let b: &noaccess [char] = &data[..];
    data.push('d'); // Does this error?

Hence the question

  • Aha, gotcha. I assume that any such reference would either do nothing or would be used by unsafe code (presumably by conversion through a raw pointer but maybe direct unsafe conversion to regular references could also be allowed).

    Your example is sneaky, though. Lifetime issues aside (suppose the next line of code uses b), that’s a noaccess reference to memory (an object? a place? I’m not sure what the current term is) that is only guaranteed to exist so long as data is not mutated. So the code with a subsequent use of data would error.

    But if it were instead:

        let b: &noaccess = data;
    

    Then it would not error.

It may be interesting to focus on how exactly these planned "no-access" references would differ from raw pointers? Access through raw pointers is an unsafe operation already.