Open CPerezz opened 3 years ago
I took a stab at fixing this here https://github.com/rusty122/wee_alloc/commit/ccae9a37ec3956cdac2df5b47cd8f54e37447d81
Current error is:
error[E0053]: method `allocate` has an incompatible type for trait
--> wee_alloc/src/lib.rs:1149:5
|
1149 | fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, AllocError> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[u8]`, found `u8`
|
= note: expected fn pointer `fn(&&'b WeeAlloc<'a>, Layout) -> std::result::Result<NonNull<[u8]>, _>`
found fn pointer `fn(&&'b WeeAlloc<'a>, Layout) -> std::result::Result<NonNull<u8>, _>`
error: aborting due to previous error
instead of a plain u8
, allocate
expects a slice and it looks like the Rust implementation is moving to NonNull::slice_from_raw_parts
. It seems like we may need the slice_from_raw_parts
nightly feature to implement the GlobalAlloc
as well
Hey sorry for not answering earlier.
You're right, at least I thought the same, I quickly did some changes with the new API and:
So if you do: #![cfg_attr( feature = "nightly", feature(nonnull_slice_from_raw_parts, slice_ptr_get) )]
Then you can refactor the internals to return what the actual core::Allocator::allocate
requires: Result<NonNull<[u8]>, AllocError>
.
This would look like:
@@ -914,7 +918,7 @@ unsafe fn alloc_first_fit<'a>(
align: Bytes,
head: &Cell<*const FreeCell<'a>>,
policy: &dyn AllocPolicy<'a>,
-) -> Result<NonNull<u8>, AllocErr> {
+) -> Result<NonNull<[u8]>, AllocErr> {
extra_assert!(size.0 > 0);
walk_free_list(head, policy, |previous, current| {
@@ -922,7 +926,12 @@ unsafe fn alloc_first_fit<'a>(
if let Some(allocated) = current.try_alloc(previous, size, align, policy) {
assert_aligned_to(allocated.data(), align);
- return Some(unchecked_unwrap(NonNull::new(allocated.data() as *mut u8)));
+ let ptr = allocated.data() as *mut u8;
+
+ return Some(NonNull::slice_from_raw_parts(
+ unchecked_unwrap(NonNull::new(ptr)),
+ align.0,
+ ));
}
None
@@ -934,7 +943,7 @@ unsafe fn alloc_with_refill<'a, 'b>(
align: Bytes,
head: &'b Cell<*const FreeCell<'a>>,
policy: &dyn AllocPolicy<'a>,
-) -> Result<NonNull<u8>, AllocErr> {
+) -> Result<NonNull<[u8]>, AllocErr> {
if let Ok(result) = alloc_first_fit(size, align, head, policy) {
return Ok(result);
}
@@ -1027,7 +1036,7 @@ impl<'a> WeeAlloc<'a> {
})
}
- unsafe fn alloc_impl(&self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
+ unsafe fn alloc_impl(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
let size = Bytes(layout.size());
let align = if layout.align() == 0 {
Bytes(1)
@@ -1039,7 +1048,10 @@ impl<'a> WeeAlloc<'a> {
// Ensure that our made up pointer is properly aligned by using the
// alignment as the pointer.
extra_assert!(align.0 > 0);
- return Ok(NonNull::new_unchecked(align.0 as *mut u8));
+ return Ok(NonNull::slice_from_raw_parts(
+ NonNull::new_unchecked(align.0 as *mut u8),
+ align.0,
+ ));
}
let word_size: Words = checked_round_up_to(size).ok_or(AllocErr)?;
@@ -1146,11 +1158,11 @@ unsafe impl<'a, 'b> Alloc for &'b WeeAlloc<'a>
where
'a: 'b,
{
- unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
- self.alloc_impl(layout)
+ fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
+ unsafe { self.alloc_impl(layout) }
}
- unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
+ unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
self.dealloc_impl(ptr, layout)
}
}
@@ -1158,7 +1170,7 @@ where
unsafe impl GlobalAlloc for WeeAlloc<'static> {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
match self.alloc_impl(layout) {
- Ok(ptr) => ptr.as_ptr(),
+ Ok(slice) => slice.get_unchecked_mut(0).as_ptr(),
Err(AllocErr) => ptr::null_mut(),
}
}
Then you'll realize that GlobalAllocator::alloc
can no longer call Allocator::allocate
unless you do:
unsafe impl GlobalAlloc for WeeAlloc<'static> {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
match self.alloc_impl(layout) {
Ok(slice) => slice.get_unchecked_mut(0).as_ptr(),
Err(AllocErr) => ptr::null_mut(),
}
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
if let Some(ptr) = NonNull::new(ptr) {
self.dealloc_impl(ptr, layout);
}
}
}
But that will force you to use #![feature(nonnull_slice_from_raw_parts)]
& #![feature(slice_ptr_get)]
for the entire crate.
And considering that the API is experimental, and the Allocator one is too, I'm not really sure that making any changes is a good option since they're likely to fall outdated or not work.
It might be really good to get @fitzgen 's input on that.
@CPerezz I think you can actually avoid enabling the experimental features by basically just inlining the Rust implementations of those methods. get_unchecked_mut
for example can be implemented as unsafe { NonNull::new_unchecked(non_null_slice.as_ptr().get_unchecked_mut(index)) }
to avoid enabling slice_ptr_get
and slice_from_raw_parts
can be done similarly.
Agreed that requiring nightly isn't great, but I think if we can update the repo to compile/run on both stable and nightly that would be good.
Couple implementation notes:
ptr.as_mut_ptr()
should be the same as ptr.get_unchecked_mut(0).as_ptr()
(https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_mut_ptr) and can be simplified to non_null_slice.as_ptr().as_mut_ptr()
- get the pointer to the slice and then a mutable pointer to the start of the slice's bufferslice_from_raw_parts
logic has an error because it's passing the size as Words instead of Bytes, so need to convert the units in alloc_first_fit
I've made some more progress on this. Most tests are passing, but there are some failures in one or two because I managed to break an invariant in the free list - will update my branch sometime today
Here's my updated branch: https://github.com/rusty122/wee_alloc/tree/update-renamed-imports-and-trait-signatures
Seems like there's a bug involving a CellHeader getting overwritten somehow :/
nvm! Bug was that in the stress test I had updated the realloc
method call to grow
, but it should actually be shrink
when the new layout is smaller than the original allocation layout. PR is up and passing the appveyor CI tests - seems like the Travis CI build hasn't been triggered, but not sure why (looks like it needs to get migrated to travis-ci.com in the next few weeks because travis-ci.org is shutting down?)
@fitzgen could you review when you get a chance, or is there someone else from the team that could review?
Describe the Bug
Execution of
.check
,.build
&.test
fails due to a compilation problem. I commented out thei686-pc-windows-gnu
target-related checks since I can't run them in my env and the compilation ofwee_alloc
fails with output:It happens the same with the other scripts.
Steps to Reproduce
Just run any of check, build or test scripts.
Expected Behavior
I would expect the imports to be correct.
Alloc
does not exist in libcore, it was renamed toAllocator
AFAIK. Same happens withAllocErr
which was renamed toAllocError
.Also the
Alloc
trait-functions have been updated.If I'm not missing something or ommiting any info. And the repo is still mantained, I would like to update that and solve this issue. Otherways, please, could you tell me what I'm missing ?