Zhiyao
Zhiyao

Reputation: 4394

Can I prevent the reference of a type from being created or used?

My primary goal is to prevent the reference of a self-defined type from being created. If it is impossible, then my secondary goal is to prevent the using of such reference.

I have a struct that is supported by a page of virtual memory. From time to time, that page may be remapped to a different address, while the content in the page is untouched. The remapping is done by the OS, so the user code is not directly notified when it happens. The OS maintains a reserved register that always points to the remappable page. The user code should follow this register to access the struct. It should not use the (Rust native) reference, because the reference becomes stale after the OS remaps the page.

As an example, assume that the remappable struct is defined as Remappable. Special reference types, e.g. RefField1, are defined for each field. volatile_deref() will follow the reserved register to read the field from the correct address.

struct Remappable {
    f1: Field1,
    f2: Field2,
    /* ... */
}

impl Remappable {
    pub fn get_ref_f1(&self) -> RefField1 { /* ... */ }
    pub fn get_ref_f2(&self) -> RefField2 { /* ... */ }
}

impl RefField1 {
    pub fn volatile_deref(&self) -> Field1 {
        /* Presumably some inline assembly taking
           atomicity (regarding the remappable page
           address) of reading into account.
           On x86 this may be achieved through
           the usage of segment registers. */
    }
}

I have no idea of how to achieve my primary goal, i.e. preventing &Remappable from being created.

I gave a naive try to my secondary goal. I did the following, but it could not work, either.

use std::ops::Deref;

impl Deref for &Remappable {
    type Target = ();
    fn deref(&self) -> &Self::Target {
        panic!()
    }
}

This is because it gives a conflicting implementation of Deref.

error[E0119]: conflicting implementations of trait `std::ops::Deref` for type `&Remappable`
 --> src/main.rs:7:1
  |
7 | impl Deref for &Remappable {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: conflicting implementation in crate `core`:
          - impl<T> Deref for &T
            where T: ?Sized;

Is there any way to achieve one of the goals?

Upvotes: 2

Views: 358

Answers (1)

Kevin Reid
Kevin Reid

Reputation: 43773

You cannot prevent the existence of references to a type. Instead, in order to make what you're describing legible to the Rust compiler, you need to make the container of that type special. That is, given that

the OS maintains a reserved register that always points to the remappable page

you should have a data type which represents that reserved register (much like, for example, Box represents a heap allocation that it manages). That data type is the one which avoids implementing Deref.

For illustration, a similar situation appears the Cell type in the Rust standard library — because it offers interior mutability, it cannot safely return references to its contents, so every operation on a Cell (except for those that know they have exclusive access, which doesn't apply to your situation) must copy data in or out rather than returning references.

Upvotes: 3

Related Questions