diff --git a/components/casemap/src/provider/exceptions.rs b/components/casemap/src/provider/exceptions.rs index d58053bc62a..133892faf67 100644 --- a/components/casemap/src/provider/exceptions.rs +++ b/components/casemap/src/provider/exceptions.rs @@ -137,6 +137,10 @@ impl ExceptionULE { #[inline] fn empty_exception() -> &'static Self { static EMPTY_BYTES: &[u8] = &[0, 0]; + // Safety: + // ExceptionULE is a packed DST with `(u8, u8, unsized)` fields. All bit patterns are valid for the two u8s + // + // An "empty" one can be constructed from a slice of two u8s unsafe { let slice: *const [u8] = ptr::slice_from_raw_parts(EMPTY_BYTES.as_ptr(), 0); &*(slice as *const Self) diff --git a/components/list/src/provider/serde_dfa.rs b/components/list/src/provider/serde_dfa.rs index da494abf0f5..7fa2f5cdb75 100644 --- a/components/list/src/provider/serde_dfa.rs +++ b/components/list/src/provider/serde_dfa.rs @@ -34,7 +34,8 @@ impl databake::Bake for SerdeDFA<'_> { env.insert("icu_list"); let le_bytes = databake::Bake::bake(&self.deref().to_bytes_little_endian().as_slice(), env); let be_bytes = databake::Bake::bake(&self.deref().to_bytes_big_endian().as_slice(), env); - // Safe because of `to_bytes_little_endian`/`to_bytes_big_endian`'s invariant. + // Safe because of `to_bytes_little_endian`/`to_bytes_big_endian`'s invariant: They produce + // valid DFA representations, and we consume them correctly taking care of the endianness of the target platform. databake::quote! { unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked( diff --git a/components/locid_transform/src/fallback/mod.rs b/components/locid_transform/src/fallback/mod.rs index 6b13e020143..9dd835419c6 100644 --- a/components/locid_transform/src/fallback/mod.rs +++ b/components/locid_transform/src/fallback/mod.rs @@ -148,7 +148,11 @@ impl LocaleFallbacker { parents: crate::provider::Baked::SINGLETON_FALLBACK_PARENTS_V1, collation_supplement: Some(crate::provider::Baked::SINGLETON_FALLBACK_SUPPLEMENT_CO_V1), }; - // Shitty covariance because the zeromaps confuse the compiler + // Safety: we're transmuting down from LocaleFallbackerBorrowed<'static> to LocaleFallbackerBorrowed<'a> + // ZeroMaps use associated types in a way that confuse the compiler which gives up and marks them + // as invariant. However, they are covariant, and in non-const code this covariance can be safely triggered + // using Yokeable::transform. In const code we must transmute. In the long run we should + // be able to `transform()` in const code, and also we will have hopefully improved map polymorphism (#3128) unsafe { core::mem::transmute(tickstatic) } } diff --git a/provider/blob/src/blob_schema.rs b/provider/blob/src/blob_schema.rs index 023b9abff40..4475b2e3236 100644 --- a/provider/blob/src/blob_schema.rs +++ b/provider/blob/src/blob_schema.rs @@ -230,6 +230,7 @@ impl<'a> ZeroMapKV<'a> for Index32U8 { } impl Index32U8 { + // Safety: Index32U8 is a transparent DST wrapper around `[u8]`, so a transmute is fine #[allow(dead_code)] pub(crate) const SENTINEL: &'static Self = unsafe { &*(&[] as *const [u8] as *const Self) }; } diff --git a/provider/core/src/response.rs b/provider/core/src/response.rs index 1b03a4fd3bb..09b11830fa5 100644 --- a/provider/core/src/response.rs +++ b/provider/core/src/response.rs @@ -390,7 +390,9 @@ where DataPayloadInner::StaticRef(r) => { let output: >::Output = f(Yokeable::transform(*r), PhantomData); - // Safety: >::Output is the same type as M2::Yokeable + // Safety: >::Output is the same type as M2::Yokeable; + // we're going from 'static to 'static, however in a generic context it's not + // clear to the compiler that that is the case. We have to use the unsafe make API to do this. let yokeable: M2::Yokeable = unsafe { M2::Yokeable::make(output) }; Yoke::new_owned(yokeable) }