diff --git a/compiler/gen/tests/gen_str.rs b/compiler/gen/tests/gen_str.rs index 3f43c4c48f..0f74d1fc02 100644 --- a/compiler/gen/tests/gen_str.rs +++ b/compiler/gen/tests/gen_str.rs @@ -526,4 +526,16 @@ mod gen_str { assert_evals_to!(r#""a" != "b""#, true, bool); assert_evals_to!(r#""a" == "b""#, false, bool); } + + #[test] + fn str_clone() { + use roc_std::RocStr; + let long = RocStr::from_slice("loremipsumdolarsitamet".as_bytes()); + let short = RocStr::from_slice("x".as_bytes()); + let empty = RocStr::from_slice("".as_bytes()); + + debug_assert_eq!(long.clone(), long); + debug_assert_eq!(short.clone(), short); + debug_assert_eq!(empty.clone(), empty); + } } diff --git a/roc_std/src/lib.rs b/roc_std/src/lib.rs index 46c5dd5817..f6a3e38b42 100644 --- a/roc_std/src/lib.rs +++ b/roc_std/src/lib.rs @@ -443,18 +443,26 @@ impl Eq for RocStr {} impl Clone for RocStr { fn clone(&self) -> Self { - if self.is_small_str() { + if self.is_small_str() || self.is_empty() { Self { elements: self.elements, length: self.length, } } else { + let capacity_size = core::mem::size_of::(); + let copy_length = self.length + capacity_size; let elements = unsafe { - let raw = libc::malloc(self.length); + let raw = libc::malloc(copy_length); - libc::memcpy(raw, self.elements as *mut libc::c_void, self.length); + libc::memcpy( + raw, + self.elements.offset(-(capacity_size as isize)) as *mut libc::c_void, + copy_length, + ); - raw as *mut u8 + *(raw as *mut usize) = self.length; + + (raw as *mut u8).add(capacity_size) }; Self {