Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decide the precise rules for operand of &raw [const|mut] #66708

Open
matthewjasper opened this issue Nov 24, 2019 · 4 comments
Open

Decide the precise rules for operand of &raw [const|mut] #66708

matthewjasper opened this issue Nov 24, 2019 · 4 comments
Labels
F-raw_ref_op `#![feature(raw_ref_op)]` T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@matthewjasper
Copy link
Contributor

matthewjasper commented Nov 24, 2019

#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;

cc #64490
cc @Centril @RalfJung @oli-obk

@matthewjasper matthewjasper added the F-raw_ref_op `#![feature(raw_ref_op)]` label Nov 24, 2019
@jonas-schievink jonas-schievink added the T-lang Relevant to the language team, which will review and decide on the PR/issue. label Nov 24, 2019
@RalfJung
Copy link
Member

"deref adjustment" doesn't mean anything to me so I am afraid I don't really understand the issue description.

@matthewjasper
Copy link
Contributor Author

I'll add some actual Rust examples soon then.

@matthewjasper
Copy link
Contributor Author

I've added some examples above.

@RalfJung
Copy link
Member

I feel like we should not allow &raw with deref coercions. That gives an entirely wrong impression, because in the following, intermediate references are being created:

let z = std::rc::Rc::new(x);
&raw const *z;

Deref coercions are currently inherently tied to references, as their type shows.

Are there any other cases that are contentious/subtle?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-raw_ref_op `#![feature(raw_ref_op)]` T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants