-
Notifications
You must be signed in to change notification settings - Fork 9
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
Crazy idea: Raw(Box/Vec/Deque)Impl<T> traits #63
Comments
This comment has been minimized.
This comment has been minimized.
I was able to implement this API for a typestate-ish-based safe upwards bump allocator: pub struct UpAlloc<'a, T>(&'a mut [MaybeUninit<T>]);
impl<'a, T> UpAlloc<'a, T> {
pub fn new(buf: &'a mut [MaybeUninit<T>]) -> Self {
UpAlloc(buf)
}
pub fn alloc_uninit(&'a mut self) -> Option<(UpBox<'a, MaybeUninit<T>>, UpAlloc<'a, T>)> {
let (start, remainder) = self.0.split_first_mut()?;
Some((UpBox(start), UpAlloc(remainder)))
}
pub fn alloc_init(&'a mut self, value: T) -> Option<(UpBox<'a, T>, UpAlloc<'a, T>)> {
let (start, remainder) = self.0.split_first_mut()?;
let start = start.write(value);
Some((UpBox(start), UpAlloc(remainder)))
}
pub fn alloc_slice_uninit(
&'a mut self,
min_len: usize,
target_len: usize,
) -> Option<(UpBox<'a, [MaybeUninit<T>]>, UpAlloc<'a, T>)> {
if min_len > self.0.len() {
None
} else if target_len > self.0.len() {
Some((UpBox(self.0), UpAlloc(&mut [])))
} else {
let (start, remainder) = self.0.split_at_mut(target_len);
Some((UpBox(start), UpAlloc(remainder)))
}
}
}
pub struct UpBox<'a, T: ?Sized>(&'a mut T);
impl<'a, T: ?Sized> Deref for UpBox<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.0
}
}
impl<'a, T: ?Sized> DerefMut for UpBox<'a, T> {
fn deref_mut(&mut self) -> &mut T {
self.0
}
}
// UNSAFE:
// - `self.0` is a reference
// - `self.0` is never modified
unsafe impl<'a, T> RawBoxImpl<T> for UpBox<'a, T> {}
unsafe impl<'a, T> RawBoxSizedImpl<T> for UpBox<'a, T> {
type OfMaybeUninit = UpBox<'a, MaybeUninit<T>>;
}
unsafe impl<'a, T> RawBoxMaybeUninitImpl<T> for UpBox<'a, MaybeUninit<T>> {
type Init = UpBox<'a, T>;
fn initialize(self, value: T) -> UpBox<'a, T> {
UpBox(self.0.write(value))
}
}
unsafe impl<'a, T> Freeze for UpBox<'a, T> {
type Frozen = &'a T;
fn freeze(self) -> &'a T {
self.0
}
unsafe fn unfreeze(frozen: &'a T) -> Self {
Self(&mut *(frozen as *const T as *mut T))
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_rc() {
use super::{UpAlloc, UpBox};
use crate::rc::Rc;
use std::mem::MaybeUninit;
let mut buf: [_; 1024] = MaybeUninit::uninit_array();
let mut alloc = UpAlloc(&mut buf);
let (x, _alloc) = alloc.alloc_uninit().unwrap();
Rc::<i32, UpBox<_>>::new_init_from_raw(x, 123);
}
} Playground: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=28dcb72cf6b64421b7302b1ed0183448 |
I've been waiting for some other people in the WG to respond to this issue, because I didn't fully comprehend the need for a solution to the described problem. As no one has responded yet, I'll give my two cents. As far as I understand, the goal of the |
Rationale
unsafe
code than necessary.Core traits
These traits do not currently include a generic way to create instances; this is expected to be done through methods on allocators. Additionally, these traits do not control zeroing; this is expected to depend on the type of the allocator. (Are there any cases where creation/resizing is sometimes non-zeroing and sometimes zeroing, for the same value?)
Instances of these traits should free their memory on drop.
Additional trait
This is used by types like
Rc
andArc
.Usage examples
See also
The text was updated successfully, but these errors were encountered: