Skip to content

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

Open
@matthewjasper

Description

@matthewjasper
Contributor

#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

Activity

RalfJung

RalfJung commented on Nov 25, 2019

@RalfJung
Member

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

matthewjasper

matthewjasper commented on Nov 25, 2019

@matthewjasper
ContributorAuthor

I'll add some actual Rust examples soon then.

matthewjasper

matthewjasper commented on Nov 28, 2019

@matthewjasper
ContributorAuthor

I've added some examples above.

RalfJung

RalfJung commented on Nov 29, 2019

@RalfJung
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

Metadata

Metadata

Assignees

No one assigned

    Labels

    F-raw_ref_op`#![feature(raw_ref_op)]`T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @RalfJung@jonas-schievink@matthewjasper

        Issue actions

          Decide the precise rules for operand of &raw [const|mut] · Issue #66708 · rust-lang/rust