Feature Idea: Add a macro to "de-magic" box syntax

I'd like some feedback on an RFC I wrote to add a macro to the standard library that abstracts over box syntax, and perhaps future methods of initializing memory on the heap.

From what I recall, the problem with "placement new" is not its syntax, it's that there doesn't currently seem to be a way to actually provide meaningful guarantees about where the data is constructed, so even if you use box syntax, the data might be constructed on the heap stack first.

Several changes to placement new have been proposed, but none of them address this issue.

6 Likes

To clarify my point above: If the new language feature does not add any hard guarantees, then it might as well just be an optimization the compiler performs opportunistically (we do have sufficient wiggle-room in the language semantics for this).

Implementing this optimization would be much less involved than going through the whole RFC process, and would provide valuable data points about whether we even need a placement new language feature. It would also likely be a prerequisite for any language-level feature.

1 Like

wiggle-room

Never underestimate the impact of Big-Library not compiling without such an optimization :stuck_out_tongue:

Why is it not possible to provide meaningful gurantees? Iirc C++ has had emplacement for a while now.

C++'s guarantees are defined in terms of which constructors (including copy/move constructors) are or are not called, which is an observable behavior from within the program.

Rust does not have constructors of any kind, or really anything that makes moves observable in that way. So one problem is figuring out a way to specify those guarantees. But even given a solution to that problem, idiomatic Rust also includes a lot of things that C++ never has to deal with- e.g. what if you want to place a value of type T constructed by a function returning Result<T, E>? This requires some new ABI functionality that does not exist anywhere yet.

(Nobody is saying that this is definitely not possible, just that none of the proposals so far have accomplished it.)

5 Likes

I'd like to propose my own solution here.

Step A: Add a method to Default trait:

trait Default {
     ....
     fn init_with_default(uninit: &mut MaybeUninit<Self>) {
           uninit.write(Self::default());
     }
}

Step B: Enhance derive(Default) to provide a field-by-field initialization implementation for this method. Also switch its current implementation for fn default() -> Self method to calling this method on a MaybeUninit value to initialize.

Step C: Change impl<T> Default for Box<T> 's default implemenation to:

impl<T> Default for Box<T> where T: Default {
     fn default() -> Self {
          let mut v = Box::<T>::new_uninit();
          T::init_with_default(v.as_mut_ptr());
          unsafe {
              v.assume_init()
          }
     }
}

With this new implementation, initializing memory on the heap is promised. You can also do custom initialization steps by writing code similiar to the code in Step C, without relying on the box syntax at all.

1 Like

This method would need to be on an unsafe trait for it to promise to fully initialise the input parameter. I’m not sure if there’s a safe way you could guarantee that it has been initialised with field-by-field initialisation :thinking:

Specialization?

unsafe trait DefaultInitialize : Default {
    default fn default_initialize(self: &mut MaybeUninit<Self>) {
        self.write(Self::default);
    }
}

default impl<T: Default> DefaultInitialize for T {}

// #[derive(Default)] implements both

Super error prone for manual implementation, of course, but it's unsafe and no worse than unsafe to implement on the Default trait, so it's fine, right?


Maybe even with super specialization powers you could add

default impl<T: DefaultInitialize> Default for T {
    default fn default() -> Self {
        let mut this = MaybeUninit::uninit();
        Self::default_initialize(&mut this);
        unsafe { this.assume_init() }
    }
}

without overlaps?

(Not necessarily saying this is a good idea, just theoretically possible)

Removed mentions of placement new syntax, focusing more on the fact that it's "magic" syntax.