Open
Description
#66671 implements a check on the operand of &raw [const|mut]
to ensure that it's not a temporary. It's similar to the check used for the left-hand operand of =
, but it only allows field and index projections when they are based on a place expression, or it there is at least one deref adjustment involved.
It's possible that we want to restrict this to "at least one deref adjustment from a reference" or some other variant that limits the use of this with overloaded deref coercions.
// The following are all currently OK
Struct A { f: (i32, u32) }
let x: A = ...;
&raw const x;
&raw const x.f;
&raw const x.f.0;
let y = &x;
&raw const y;
&raw const *y;
&raw const (*y).f;
&raw const y.f; // Same as above
&raw const (*y).f.0;
&raw const y.f.0; // Same as above
// There's no distinction between `&T` and `Rc<T>`
use std::rc::Rc;
use std::ops::Deref;
let z = std::rc::Rc::new(x);
&raw const z;
&raw const *(z.deref());
&raw const *z; // Same as above
&raw const (*z).f;
&raw const z.f; // Same as above
&raw const (*z).f.0;
&raw const z.f.0; // Same as above
// The following are not allowed:
&raw const A { ... };
&raw const A { ... }.f;
&raw const A { ... }.f.0;
// These are allowed:
const X: &A = ...;
&raw const *X;
&raw const X.f;
&raw const X.f.0;
// These are allowed, because they can't easily be distinguished from the above. They all result in immediately dangling pointers.
&raw const *(&A { ... });
&raw const (&A { ... }).f;
&raw const (&A { ... }).f.0;
// These are also allowed, and seem even more dubious.
&raw const *Rc::new(A { ... });
&raw const Rc::new(A { ... }).f;
&raw const Rc::new(A { ... }).f.0;