rust-lang / rust-lang/rfcs

Allow (unsafe) static cast from unsafe pointer to static reference

Open
#1,691 20 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

T-lang
Dominant language
Markdown
Stars
6.6k
Forks
1.7k
Avg merge
16h 14m
Merged PRs (30d)
1

Description

There should be some way to (unsafely) cast an unsafe pointer to a 'static reference in static variables.

In scenarios like where you want to wrap a set of hardware registers in a struct, it can be very useful to initialize that it statically. It's currently almost, but not quite, possible to this.

For example, if I want to wrap the registers in a struct like:

struct Registers {
  status: VolatileCell<usize>,
  control: VolatileCell<usize>,
  ...
}

It's impossible to initialize the following global variable from a memory mapped I/O address:

static GPIO: &'static Registers;

The two options for casting from a *const T to a &'static T are:

  1. transmute which is not a const-fn and therefore can't be called from a static initializer.
  2. &* which is not allowed in statics because the initial deference cannot be done at compile time (although the combined operation is clearly possible since it's just type-cast).

There are currently two workarounds I'm aware of. First, you could declare the memory mapped I/O address in an external library (in C, assembly, or maybe a linker script) and import it using an extern block. This has the disadvantage of allowing any crate to import the same symbol, even with different types (it doesn't even require unsafe). The second option is to define a special reference type, e.g.:

struct StaticRef<T>(*const T);

impl<T> StaticRef<T> {
    pub const unsafe fn new(ptr: *const T) -> StaticRef {
        StaticRef(ptr)
    } 
}

impl<T> Deref for StaticRef<T> {
    type Target = T;
    fn deref(&self) -> &T { unsafe { &*self.0 } }
}

(Please don't use the above code uncritically if you come upon this issue, I haven't thought hard about whether this is a safe interface)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the issue's examples of transmute, &*, and the StaticRef workaround, then examine the constraints around const evaluation and 'static references. Done means identifying and specifying a sound way to initialize a static reference from an unsafe pointer, including the safety implications and limitations.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.