Skip to content
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

Add SingleBox::leak to provide access to a &'static mut #8

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/alloc_single.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,21 @@ impl<'a, T> SingleBox<'a, T> {
fn as_ptr(&self) -> *mut T {
self.single.storage.get()
}

/// Consumes and leaks the SingleBox, returning a mutable reference, &'b mut T.
///
/// If the underlying AllocSingle has static lifetime, this can return a &'static mut.
///
/// This will prevent T's destructor from being called.
pub fn leak<'b>(self) -> &'b mut T
where T: 'b,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this extra 'b lifetime? If 'a is 'static already, won't returning &'a mut T already get you the static lifetime?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not 100% sure!
If 'a is 'static and we want a &'static mut T, then sure, that would work.
But what if we actually need a shorter lifetime? I guess it's still fine because &'a T is covariant in 'a, https://doc.rust-lang.org/reference/subtyping.html#variance, so any &'a T is a subtype of &'static T for all lifetimes 'a?

'a: 'b,
{
let value = core::mem::ManuallyDrop::new(self);
let ptr = value.as_ptr();
// Safety: We leak self, so the reference stays valid as long as T and 'a are valid
unsafe { &mut *ptr }
}
}

impl<'a, T> Drop for SingleBox<'a, T> {
Expand Down Expand Up @@ -162,5 +177,9 @@ pub mod test {
// look ma no stack
let bx3 = SINGLE_DEMO.alloc_const_val().unwrap();
println!("{:?}", bx3.deref());

// we can get a &'static mut:
let bx3_ref: &'static mut _ = bx3.leak();
println!("{:?}", bx3_ref);
}
}