fix roc_std to support seamless str slices

This commit is contained in:
Brendan Hansknecht 2023-03-14 15:06:17 -07:00
parent 3978059aa2
commit 18e6dbd163
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
2 changed files with 17 additions and 10 deletions

View file

@ -94,18 +94,18 @@ impl<T> RocList<T> {
} }
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.length self.length & (isize::MAX as usize)
} }
pub fn is_seamless_slice(&self) -> bool { pub fn is_seamless_slice(&self) -> bool {
(self.capacity_or_ref_ptr as isize) < 0 ((self.length | self.capacity_or_ref_ptr) as isize) < 0
} }
pub fn capacity(&self) -> usize { pub fn capacity(&self) -> usize {
if !self.is_seamless_slice() { if !self.is_seamless_slice() {
self.capacity_or_ref_ptr self.capacity_or_ref_ptr
} else { } else {
self.length self.len()
} }
} }
@ -257,8 +257,10 @@ where
// Copy the old elements to the new allocation. // Copy the old elements to the new allocation.
unsafe { unsafe {
copy_nonoverlapping(elements.as_ptr(), new_elements.as_ptr(), self.length); copy_nonoverlapping(elements.as_ptr(), new_elements.as_ptr(), self.len());
} }
// Clear the seamless slice bit since we now have clear ownership.
self.length = self.len();
new_elements new_elements
} }
@ -295,7 +297,7 @@ impl<T> RocList<T> {
/// ///
/// May return a new RocList, if the provided one was not unique. /// May return a new RocList, if the provided one was not unique.
pub fn reserve(&mut self, num_elems: usize) { pub fn reserve(&mut self, num_elems: usize) {
let new_len = num_elems + self.length; let new_len = num_elems + self.len();
let new_elems; let new_elems;
let old_elements_ptr; let old_elements_ptr;
@ -338,7 +340,7 @@ impl<T> RocList<T> {
unsafe { unsafe {
// Copy the old elements to the new allocation. // Copy the old elements to the new allocation.
copy_nonoverlapping(old_elements_ptr, new_elems.as_ptr(), self.length); copy_nonoverlapping(old_elements_ptr, new_elems.as_ptr(), self.len());
} }
// Decrease the current allocation's reference count. // Decrease the current allocation's reference count.
@ -371,7 +373,7 @@ impl<T> RocList<T> {
self.update_to(Self { self.update_to(Self {
elements: Some(new_elems), elements: Some(new_elems),
length: self.length, length: self.len(),
capacity_or_ref_ptr: new_len, capacity_or_ref_ptr: new_len,
}); });
} }
@ -392,7 +394,7 @@ impl<T> Deref for RocList<T> {
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
if let Some(elements) = self.elements { if let Some(elements) = self.elements {
let elements = ptr::slice_from_raw_parts(elements.as_ptr().cast::<T>(), self.length); let elements = ptr::slice_from_raw_parts(elements.as_ptr().cast::<T>(), self.len());
unsafe { &*elements } unsafe { &*elements }
} else { } else {
@ -424,7 +426,7 @@ where
{ {
fn partial_cmp(&self, other: &RocList<U>) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &RocList<U>) -> Option<cmp::Ordering> {
// If one is longer than the other, use that as the ordering. // If one is longer than the other, use that as the ordering.
match self.length.partial_cmp(&other.length) { match self.len().partial_cmp(&other.len()) {
Some(Ordering::Equal) => {} Some(Ordering::Equal) => {}
ord => return ord, ord => return ord,
} }
@ -448,7 +450,7 @@ where
{ {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
// If one is longer than the other, use that as the ordering. // If one is longer than the other, use that as the ordering.
match self.length.cmp(&other.length) { match self.len().cmp(&other.len()) {
Ordering::Equal => {} Ordering::Equal => {}
ord => return ord, ord => return ord,
} }

View file

@ -698,6 +698,11 @@ impl From<SendSafeRocStr> for RocStr {
#[repr(C)] #[repr(C)]
union RocStrInner { union RocStrInner {
// TODO: this really should be separated from the List type.
// Due to length specifying seamless slices for Str and capacity for Lists they should not share the same code.
// Currently, there are work arounds in RocList to handle both via removing the highest bit of length in many cases.
// With glue changes, we should probably rewrite these cleanly to match what is in the zig bitcode.
// It is definitely a bit stale now and I think the storage mechanism can be quite confusing with our extra pieces of state.
heap_allocated: ManuallyDrop<RocList<u8>>, heap_allocated: ManuallyDrop<RocList<u8>>,
small_string: SmallString, small_string: SmallString,
} }