Skip to content
Draft
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions components/casemap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

#![feature(ptr_metadata)]

//! Case mapping for Unicode characters and strings.
//!
//! This module is published as its own crate ([`icu_casemap`](https://docs.rs/icu_casemap/latest/icu_casemap/))
Expand Down
1 change: 1 addition & 0 deletions components/collections/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
)
)]
#![warn(missing_docs)]
#![feature(ptr_metadata)]

#[cfg(feature = "alloc")]
extern crate alloc;
Expand Down
2 changes: 2 additions & 0 deletions components/datetime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

#![cfg(ptr_metadata)]
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

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

This should be #![feature(ptr_metadata)] to enable the feature, not #![cfg(ptr_metadata)] which is a conditional compilation attribute.

Suggested change
#![cfg(ptr_metadata)]
#![feature(ptr_metadata)]

Copilot uses AI. Check for mistakes.


//! Localized formatting of dates, times, and time zones.
//!
//! This module is published as its own crate ([`icu_datetime`](https://docs.rs/icu_datetime/latest/icu_datetime/))
Expand Down
2 changes: 2 additions & 0 deletions components/decimal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

#![feature(ptr_metadata)]

//! Formatting basic decimal numbers.
//!
//! This module is published as its own crate ([`icu_decimal`](https://docs.rs/icu_decimal/latest/icu_decimal/))
Expand Down
2 changes: 2 additions & 0 deletions components/locale/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

#![feature(ptr_metadata)]

//! Canonicalization of locale identifiers based on [`CLDR`] data.
//!
//! This module is published as its own crate ([`icu_locale`](https://docs.rs/icu_locale/latest/icu_locale/))
Expand Down
1 change: 1 addition & 0 deletions components/plurals/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
)
)]
#![warn(missing_docs)]
#![feature(ptr_metadata)]

extern crate alloc;

Expand Down
9 changes: 3 additions & 6 deletions utils/zerovec/derive/src/varule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,9 @@ pub fn derive_impl(
// Safety: The invariants of this function allow us to assume bytes is valid, and
// having at least #ule_size bytes is a validity constraint for the ULE type.
let unsized_bytes = bytes.get_unchecked(#ule_size..);
let unsized_ref = <#unsized_field as zerovec::ule::VarULE>::from_bytes_unchecked(unsized_bytes);
// We should use the pointer metadata APIs here when they are stable: https://github.com/rust-lang/rust/issues/81513
// For now we rely on all DST metadata being a usize to extract it via a fake slice pointer
let (_ptr, metadata): (usize, usize) = ::core::mem::transmute(unsized_ref);
let entire_struct_as_slice: *const [u8] = ::core::slice::from_raw_parts(bytes.as_ptr(), metadata);
&*(entire_struct_as_slice as *const Self)
let metadata = core::ptr::metadata(unsized_bytes);

&*core::ptr::from_raw_parts::<Self>(bytes as *const [u8] as *const u8, metadata)
}
}
}
Expand Down
10 changes: 8 additions & 2 deletions utils/zerovec/src/cow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,14 @@ impl<'a, V: VarULE + ?Sized> VarZeroCow<'a, V> {
/// Construct a new borrowed version of this
#[cfg(feature = "alloc")]
pub fn new_owned(val: Box<V>) -> Self {
let val = ManuallyDrop::new(val);
let buf: NonNull<[u8]> = val.as_bytes().into();
let len = val.as_bytes().len();
let raw_v = Box::into_raw(val) as *mut V;
// disallowed?
// let raw_u8: *mut u8 = raw_v as *mut [u8] as *mut u8;
let raw_u8: *mut u8 = raw_v as *mut () as *mut u8;
Comment on lines +190 to +192
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

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

The commented-out line and the current cast through *mut () suggest uncertainty about the correct approach. This should be clarified with a proper explanation or the commented code should be removed.

Suggested change
// disallowed?
// let raw_u8: *mut u8 = raw_v as *mut [u8] as *mut u8;
let raw_u8: *mut u8 = raw_v as *mut () as *mut u8;
// SAFETY: `V: VarULE` guarantees that the memory layout of `V` is a valid byte slice,
// and `Box<V>` is heap-allocated, so it is safe to treat its pointer as a pointer to bytes.
let raw_u8: *mut u8 = raw_v as *mut u8;

Copilot uses AI. Check for mistakes.


let buf: NonNull<[u8]> =
unsafe { NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(raw_u8, len)) };
let raw = RawVarZeroCow {
// Invariants upheld:
// 1 & 3: The bytes came from `val` so they're a valid value and byte slice
Expand Down
1 change: 1 addition & 0 deletions utils/zerovec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

#![feature(ptr_metadata)]
//! Zero-copy vector abstractions for arbitrary types, backed by byte slices.
//!
//! `zerovec` enables a far wider range of types — beyond just `&[u8]` and `&str` — to participate in
Expand Down
10 changes: 7 additions & 3 deletions utils/zerovec/src/ule/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,18 @@ pub fn encode_varule_to_box<S: EncodeAsVarULE<T> + ?Sized, T: VarULE + ?Sized>(x
// zero-fill the vector to avoid uninitialized data UB
let mut vec: Vec<u8> = vec![0; x.encode_var_ule_len()];
x.encode_var_ule_write(&mut vec);
let boxed = mem::ManuallyDrop::new(vec.into_boxed_slice());
let boxed = vec.into_boxed_slice();
unsafe {
// Safety: `ptr` is a box, and `T` is a VarULE which guarantees it has the same memory layout as `[u8]`
// and can be recouped via from_bytes_unchecked()
let ptr: *mut T = T::from_bytes_unchecked(&boxed) as *const T as *mut T;
let ptr = T::from_bytes_unchecked(&boxed) as *const T;
let metadata = core::ptr::metadata(ptr);

// Safety: we can construct an owned version since we have mem::forgotten the older owner
Box::from_raw(ptr)
Box::from_raw(core::ptr::from_raw_parts_mut(
Box::into_raw(boxed) as *mut [u8] as *mut u8,
metadata,
))
}
}

Expand Down
11 changes: 7 additions & 4 deletions utils/zerovec/src/ule/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,13 +362,16 @@ pub unsafe trait VarULE: 'static {
use alloc::boxed::Box;
use core::alloc::Layout;
let bytesvec = self.as_bytes().to_owned().into_boxed_slice();
let bytesvec = mem::ManuallyDrop::new(bytesvec);

unsafe {
// Get the pointer representation
let ptr: *mut Self = Self::from_bytes_unchecked(&bytesvec) as *const Self as *mut Self;
assert_eq!(Layout::for_value(&*ptr), Layout::for_value(&**bytesvec));
let ptr = Self::from_bytes_unchecked(&bytesvec) as *const Self;
let metadata = core::ptr::metadata(ptr);
// Transmute the pointer to an owned pointer
Box::from_raw(ptr)
Box::from_raw(core::ptr::from_raw_parts_mut(
Box::into_raw(bytesvec) as *mut [u8] as *mut u8,
metadata,
))
}
}
}
Expand Down
Loading