chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

1
vendor/yoke/.cargo-checksum.json vendored Normal file
View File

@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"25ec21fea0ddceb27a20655df8d7f94725327df58ba514ab44f949158c41bda0","Cargo.lock":"14fcadcc10c9a50c883f215187c439c4fb5016acf9575fea1694596d30c97740","Cargo.toml":"2c43e6167fab448a0ae25c20f07e262b53e426dc6270dc7fc6fb7f6684ff9eeb","Cargo.toml.orig":"6bde033bfe51959c01477b9ded71ee85cbba67db5fbadb3d4489764f4dcdd5be","LICENSE":"f367c1b8e1aa262435251e442901da4607b4650e0e63a026f5044473ecfb90f2","README.md":"7caeea392483abdb034071f43cd056c7a69940b77a0e65ad7f37f4657107d4a3","src/cartable_ptr.rs":"04082c417fe8a4a92e25f975d25155d18723991e01a5fd4afcbd60a0dcf60743","src/either.rs":"1ee107f5767a08255cec3124fe6d98a9a88ecaaf39f8987e5fb077cd8b97106e","src/erased.rs":"ebd156e832b5e67c599c6938cfbe85cd11a6088818a6981f56911cffb49e0a5f","src/kinda_sorta_dangling.rs":"caff4ee5ef690e6f6c4101d7b6c7005ce8a10e6e0c13b07914e937801d5e9ab3","src/lib.rs":"78540e102eae5b4983f460e567fa112b9349ffbb234dd7723bdabf6fe2413fa6","src/macro_impls.rs":"e116abc4eed9a6ddfe0c553f5d83de3382de954b21ef1c35020f0a40bc012a31","src/utils.rs":"57b56ae0cdae9b27a2d522f41546779f3ef34e6601507015a29ac817d4e3b204","src/yoke.rs":"050a99be4fb54719ba1336da12415c690664c2786387ff33f67ea54a99a679f5","src/yokeable.rs":"ca99e919b4086f9b4c8689591769d2012dfbd6ca6251b544c44ec76fd3d2bef1","src/zero_from.rs":"4a63f2d340ee134d10e7ad9f5472f2d21913216a524c7cfc941c31fc9e2e1cae","tests/bincode.rs":"869d4601d829c64d2dcd046134455a72be448de639d0b2e61baa9cfc4e114050","tests/miri.rs":"fd119cfbf1abc39463e3be5145966962853d1f6771826c003449a06b3e8acbea"},"package":"72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"}

6
vendor/yoke/.cargo_vcs_info.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "29dfe2790b6cfdab94ca6a6b69f58ce54802dbf7"
},
"path_in_vcs": "utils/yoke"
}

178
vendor/yoke/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,178 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "cobs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
dependencies = [
"thiserror",
]
[[package]]
name = "postcard"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
dependencies = [
"cobs",
"serde",
]
[[package]]
name = "proc-macro2"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
[[package]]
name = "syn"
version = "2.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "synstructure"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thiserror"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06"
[[package]]
name = "yoke"
version = "0.8.1"
dependencies = [
"bincode",
"postcard",
"serde",
"stable_deref_trait",
"yoke-derive",
"zerofrom",
]
[[package]]
name = "yoke-derive"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "zerofrom"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]

113
vendor/yoke/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,113 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.82"
name = "yoke"
version = "0.8.1"
authors = ["Manish Goregaokar <manishsmail@gmail.com>"]
build = false
include = [
"data/**/*",
"src/**/*",
"examples/**/*",
"benches/**/*",
"tests/**/*",
"Cargo.toml",
"LICENSE",
"README.md",
"build.rs",
]
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Abstraction allowing borrowed data to be carried along with the backing data it borrows from"
readme = "README.md"
keywords = [
"zerocopy",
"serialization",
"lifetime",
"borrow",
"self-referential",
]
categories = [
"data-structures",
"memory-management",
"caching",
"no-std",
]
license = "Unicode-3.0"
repository = "https://github.com/unicode-org/icu4x"
[package.metadata.workspaces]
independent = true
[package.metadata.docs.rs]
all-features = true
[package.metadata.cargo-all-features]
max_combination_size = 3
[features]
alloc = [
"stable_deref_trait/alloc",
"zerofrom/alloc",
]
default = [
"alloc",
"zerofrom",
]
derive = [
"dep:yoke-derive",
"zerofrom/derive",
]
serde = []
zerofrom = ["dep:zerofrom"]
[lib]
name = "yoke"
path = "src/lib.rs"
[[test]]
name = "bincode"
path = "tests/bincode.rs"
[[test]]
name = "miri"
path = "tests/miri.rs"
[dependencies.stable_deref_trait]
version = "1.2.0"
default-features = false
[dependencies.yoke-derive]
version = "0.8.0"
optional = true
default-features = false
[dependencies.zerofrom]
version = "0.1.3"
optional = true
default-features = false
[dev-dependencies.bincode]
version = "1.3.1"
[dev-dependencies.postcard]
version = "1.0.3"
default-features = false
[dev-dependencies.serde]
version = "1.0.220"
default-features = false

46
vendor/yoke/LICENSE vendored Normal file
View File

@@ -0,0 +1,46 @@
UNICODE LICENSE V3
COPYRIGHT AND PERMISSION NOTICE
Copyright © 2020-2024 Unicode, Inc.
NOTICE TO USER: Carefully read the following legal agreement. BY
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
Permission is hereby granted, free of charge, to any person obtaining a
copy of data files and any associated documentation (the "Data Files") or
software and any associated documentation (the "Software") to deal in the
Data Files or Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, and/or sell
copies of the Data Files or Software, and to permit persons to whom the
Data Files or Software are furnished to do so, provided that either (a)
this copyright and permission notice appear with all copies of the Data
Files or Software, or (b) this copyright and permission notice appear in
associated Documentation.
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
FILES OR SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall
not be used in advertising or otherwise to promote the sale, use or other
dealings in these Data Files or Software without prior written
authorization of the copyright holder.
SPDX-License-Identifier: Unicode-3.0
Portions of ICU4X may have been adapted from ICU4C and/or ICU4J.
ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation and others.

31
vendor/yoke/README.md vendored Normal file
View File

@@ -0,0 +1,31 @@
# yoke [![crates.io](https://img.shields.io/crates/v/yoke)](https://crates.io/crates/yoke)
<!-- cargo-rdme start -->
This crate provides [`Yoke<Y, C>`][Yoke], which allows one to "yoke" (attach) a zero-copy deserialized
object (say, a [`Cow<'a, str>`](alloc::borrow::Cow)) to the source it was deserialized from, (say, an [`Rc<[u8]>`](alloc::rc::Rc)),
known in this crate as a "cart", producing a type that looks like `Yoke<Cow<'static, str>, Rc<[u8]>>`
and can be moved around with impunity.
Succinctly, this allows one to "erase" static lifetimes and turn them into dynamic ones, similarly
to how `dyn` allows one to "erase" static types and turn them into dynamic ones.
Most of the time the yokeable `Y` type will be some kind of zero-copy deserializable
abstraction, potentially with an owned variant (like [`Cow`](alloc::borrow::Cow),
[`ZeroVec`](https://docs.rs/zerovec), or an aggregate containing such types), and the cart `C` will be some smart pointer like
[`Box<T>`](alloc::boxed::Box), [`Rc<T>`](alloc::rc::Rc), or [`Arc<T>`](std::sync::Arc), potentially wrapped in an [`Option<T>`](Option).
The key behind this crate is [`Yoke::get()`], where calling [`.get()`][Yoke::get] on a type like
`Yoke<Cow<'static, str>, _>` will get you a short-lived `&'a Cow<'a, str>`, restricted to the
lifetime of the borrow used during [`.get()`](Yoke::get). This is entirely safe since the `Cow` borrows from
the cart type `C`, which cannot be interfered with as long as the `Yoke` is borrowed by [`.get()`](Yoke::get).
[`.get()`](Yoke::get) protects access by essentially reifying the erased lifetime to a safe local one
when necessary.
See the documentation of [`Yoke`] for more details.
<!-- cargo-rdme end -->
## More Information
For more information on development, authorship, contributing etc. please visit [`ICU4X home page`](https://github.com/unicode-org/icu4x).

445
vendor/yoke/src/cartable_ptr.rs vendored Normal file
View File

@@ -0,0 +1,445 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
//! Types for optional pointers with niche optimization.
//!
//! The main type is [`CartableOptionPointer`], which is like `Option<Rc>` but
//! with a niche so that the resulting `Yoke` has a niche. The following four
//! types can be stored in the `CartableOptionPointer`:
//!
//! 1. `&T`
//! 2. `Box<T>`
//! 3. `Rc<T>`
//! 4. `Arc<T>`
//!
//! These four types implement the sealed unsafe trait [`CartablePointerLike`].
//! In addition, all except `Box<T>` impl [`CloneableCartablePointerLike`],
//! which allows [`CartableOptionPointer`] to implement `Clone`.
use crate::CloneableCart;
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use alloc::rc::Rc;
#[cfg(feature = "alloc")]
use alloc::sync::Arc;
#[cfg(test)]
use core::cell::Cell;
use core::marker::PhantomData;
use core::ptr::NonNull;
use stable_deref_trait::StableDeref;
// Safety note: this method MUST return the same value for the same T, even if i.e. the method gets
// instantiated in different crates. This can be untrue in surprising ways! For example, just
// returning a const-ref-to-const would not guarantee that.
// The current implementation always returns the same address for any T, see
// [the reference](https://doc.rust-lang.org/reference/items/static-items.html#statics--generics):
// there is exactly one `SENTINEL` item for any T.
#[inline]
fn sentinel_for<T>() -> NonNull<T> {
static SENTINEL: &u8 = &0x1a; // SUB
// Safety: SENTINEL is indeed not a null pointer, even after the casts.
unsafe { NonNull::new_unchecked(SENTINEL as *const u8 as *mut T) }
}
#[cfg(test)]
thread_local! {
static DROP_INVOCATIONS: Cell<usize> = const { Cell::new(0) };
}
mod private {
pub trait Sealed {}
}
use private::Sealed;
/// An object fully representable by a non-null pointer.
///
/// # Safety
///
/// Implementer safety:
///
/// 1. `into_raw` transfers ownership of the values referenced by StableDeref to the caller,
/// if there is ownership to transfer
/// 2. `drop_raw` returns ownership back to the impl, if there is ownership to transfer
///
/// Note: if `into_raw` returns the sentinel pointer, memory leaks may occur, but this will not
/// lead to undefined behaviour.
///
/// Note: the pointer `NonNull<Self::Raw>` may or may not be aligned and it should never
/// be dereferenced. Rust allows unaligned pointers; see [`std::ptr::read_unaligned`].
pub unsafe trait CartablePointerLike: StableDeref + Sealed {
/// The raw type used for [`Self::into_raw`] and [`Self::drop_raw`].
#[doc(hidden)]
type Raw;
/// Converts this pointer-like into a pointer.
#[doc(hidden)]
fn into_raw(self) -> NonNull<Self::Raw>;
/// Drops any memory associated with this pointer-like.
///
/// # Safety
///
/// Caller safety:
///
/// 1. The pointer MUST have been returned by this impl's `into_raw`.
/// 2. The pointer MUST NOT be dangling.
#[doc(hidden)]
unsafe fn drop_raw(pointer: NonNull<Self::Raw>);
}
/// An object that implements [`CartablePointerLike`] that also
/// supports cloning without changing the address of referenced data.
///
/// # Safety
///
/// Implementer safety:
///
/// 1. `addref_raw` must create a new owner such that an additional call to
/// `drop_raw` does not create a dangling pointer
/// 2. `addref_raw` must not change the address of any referenced data.
pub unsafe trait CloneableCartablePointerLike: CartablePointerLike {
/// Clones this pointer-like.
///
/// # Safety
///
/// Caller safety:
///
/// 1. The pointer MUST have been returned by this impl's `into_raw`.
/// 2. The pointer MUST NOT be dangling.
#[doc(hidden)]
unsafe fn addref_raw(pointer: NonNull<Self::Raw>);
}
impl<'a, T> Sealed for &'a T {}
// Safety:
// 1. There is no ownership to transfer
// 2. There is no ownership to transfer
unsafe impl<'a, T> CartablePointerLike for &'a T {
type Raw = T;
#[inline]
fn into_raw(self) -> NonNull<T> {
self.into()
}
#[inline]
unsafe fn drop_raw(_pointer: NonNull<T>) {
// No-op: references are borrowed from elsewhere
}
}
// Safety:
// 1. There is no ownership
// 2. The impl is a no-op so no addresses are changed.
unsafe impl<'a, T> CloneableCartablePointerLike for &'a T {
#[inline]
unsafe fn addref_raw(_pointer: NonNull<T>) {
// No-op: references are borrowed from elsewhere
}
}
#[cfg(feature = "alloc")]
impl<T> Sealed for Box<T> {}
#[cfg(feature = "alloc")]
// Safety:
// 1. `Box::into_raw` says: "After calling this function, the caller is responsible for the
// memory previously managed by the Box."
// 2. `Box::from_raw` says: "After calling this function, the raw pointer is owned by the
// resulting Box."
unsafe impl<T> CartablePointerLike for Box<T> {
type Raw = T;
#[inline]
fn into_raw(self) -> NonNull<T> {
// Safety: `Box::into_raw` says: "The pointer will be properly aligned and non-null."
unsafe { NonNull::new_unchecked(Box::into_raw(self)) }
}
#[inline]
unsafe fn drop_raw(pointer: NonNull<T>) {
// Safety: per the method's precondition, `pointer` is dereferenceable and was returned by
// `Self::into_raw`, i.e. by `Box::into_raw`. In this circumstances, calling
// `Box::from_raw` is safe.
let _box = unsafe { Box::from_raw(pointer.as_ptr()) };
// Boxes are always dropped
#[cfg(test)]
DROP_INVOCATIONS.with(|x| x.set(x.get() + 1))
}
}
#[cfg(feature = "alloc")]
impl<T> Sealed for Rc<T> {}
#[cfg(feature = "alloc")]
// Safety:
// 1. `Rc::into_raw` says: "Consumes the Rc, returning the wrapped pointer. To avoid a memory
// leak the pointer must be converted back to an Rc using Rc::from_raw."
// 2. See 1.
unsafe impl<T> CartablePointerLike for Rc<T> {
type Raw = T;
#[inline]
fn into_raw(self) -> NonNull<T> {
// Safety: Rcs must contain data (and not be null)
unsafe { NonNull::new_unchecked(Rc::into_raw(self) as *mut T) }
}
#[inline]
unsafe fn drop_raw(pointer: NonNull<T>) {
// Safety: per the method's precondition, `pointer` is dereferenceable and was returned by
// `Self::into_raw`, i.e. by `Rc::into_raw`. In this circumstances, calling
// `Rc::from_raw` is safe.
let _rc = unsafe { Rc::from_raw(pointer.as_ptr()) };
// Rc is dropped if refcount is 1
#[cfg(test)]
if Rc::strong_count(&_rc) == 1 {
DROP_INVOCATIONS.with(|x| x.set(x.get() + 1))
}
}
}
#[cfg(feature = "alloc")]
// Safety:
// 1. The impl increases the refcount such that `Drop` will decrease it.
// 2. The impl increases refcount without changing the address of data.
unsafe impl<T> CloneableCartablePointerLike for Rc<T> {
#[inline]
unsafe fn addref_raw(pointer: NonNull<T>) {
// Safety: The caller safety of this function says that:
// 1. The pointer was obtained through Rc::into_raw
// 2. The associated Rc instance is valid
// Further, this impl is not defined for anything but the global allocator.
unsafe {
Rc::increment_strong_count(pointer.as_ptr());
}
}
}
#[cfg(feature = "alloc")]
impl<T> Sealed for Arc<T> {}
#[cfg(feature = "alloc")]
// Safety:
// 1. `Rc::into_raw` says: "Consumes the Arc, returning the wrapped pointer. To avoid a memory
// leak the pointer must be converted back to an Arc using Arc::from_raw."
// 2. See 1.
unsafe impl<T> CartablePointerLike for Arc<T> {
type Raw = T;
#[inline]
fn into_raw(self) -> NonNull<T> {
// Safety: Arcs must contain data (and not be null)
unsafe { NonNull::new_unchecked(Arc::into_raw(self) as *mut T) }
}
#[inline]
unsafe fn drop_raw(pointer: NonNull<T>) {
// Safety: per the method's precondition, `pointer` is dereferenceable and was returned by
// `Self::into_raw`, i.e. by `Rc::into_raw`. In this circumstances, calling
// `Rc::from_raw` is safe.
let _arc = unsafe { Arc::from_raw(pointer.as_ptr()) };
// Arc is dropped if refcount is 1
#[cfg(test)]
if Arc::strong_count(&_arc) == 1 {
DROP_INVOCATIONS.with(|x| x.set(x.get() + 1))
}
}
}
#[cfg(feature = "alloc")]
// Safety:
// 1. The impl increases the refcount such that `Drop` will decrease it.
// 2. The impl increases refcount without changing the address of data.
unsafe impl<T> CloneableCartablePointerLike for Arc<T> {
#[inline]
unsafe fn addref_raw(pointer: NonNull<T>) {
// Safety: The caller safety of this function says that:
// 1. The pointer was obtained through Arc::into_raw
// 2. The associated Arc instance is valid
// Further, this impl is not defined for anything but the global allocator.
unsafe {
Arc::increment_strong_count(pointer.as_ptr());
}
}
}
/// A type with similar semantics as `Option<C<T>>` but with a niche.
///
/// This type cannot be publicly constructed. To use this in a `Yoke`, see
/// [`Yoke::convert_cart_into_option_pointer`].
///
/// [`Yoke::convert_cart_into_option_pointer`]: crate::Yoke::convert_cart_into_option_pointer
#[derive(Debug)]
pub struct CartableOptionPointer<C>
where
C: CartablePointerLike,
{
/// The inner pointer.
///
/// # Invariants
///
/// 1. Must be either `SENTINEL_PTR` or created from `CartablePointerLike::into_raw`
/// 2. If non-sentinel, must _always_ be for a valid SelectedRc
inner: NonNull<C::Raw>,
_cartable: PhantomData<C>,
}
impl<C> CartableOptionPointer<C>
where
C: CartablePointerLike,
{
/// Creates a new instance corresponding to a `None` value.
#[inline]
pub(crate) fn none() -> Self {
Self {
inner: sentinel_for::<C::Raw>(),
_cartable: PhantomData,
}
}
/// Creates a new instance corresponding to a `Some` value.
#[inline]
pub(crate) fn from_cartable(cartable: C) -> Self {
let inner = cartable.into_raw();
debug_assert_ne!(inner, sentinel_for::<C::Raw>());
Self {
inner,
_cartable: PhantomData,
}
}
/// Returns whether this instance is `None`. From the return value:
///
/// - If `true`, the instance is `None`
/// - If `false`, the instance is a valid `SelectedRc`
#[inline]
pub fn is_none(&self) -> bool {
self.inner == sentinel_for::<C::Raw>()
}
}
impl<C> Drop for CartableOptionPointer<C>
where
C: CartablePointerLike,
{
#[inline]
fn drop(&mut self) {
let ptr = self.inner;
if ptr != sentinel_for::<C::Raw>() {
// By the invariants, `ptr` is a valid raw value since it's
// either that or sentinel, and we just checked for sentinel.
// We will replace it with the sentinel and then drop `ptr`.
self.inner = sentinel_for::<C::Raw>();
// Safety: by the invariants, `ptr` is a valid raw value.
unsafe { C::drop_raw(ptr) }
}
}
}
impl<C> Clone for CartableOptionPointer<C>
where
C: CloneableCartablePointerLike,
{
#[inline]
fn clone(&self) -> Self {
let ptr = self.inner;
if ptr != sentinel_for::<C::Raw>() {
// By the invariants, `ptr` is a valid raw value since it's
// either that or sentinel, and we just checked for sentinel.
// Safety: by the invariants, `ptr` is a valid raw value.
unsafe { C::addref_raw(ptr) }
}
Self {
inner: self.inner,
_cartable: PhantomData,
}
}
}
// Safety: logically an Option<C>. Has same bounds as Option<C>.
// The `StableDeref` parts of `C` continue to be `StableDeref`.
unsafe impl<C> CloneableCart for CartableOptionPointer<C> where
C: CloneableCartablePointerLike + CloneableCart
{
}
// Safety: logically an Option<C>. Has same bounds as Option<C>
unsafe impl<C> Send for CartableOptionPointer<C> where C: Sync + CartablePointerLike {}
// Safety: logically an Option<C>. Has same bounds as Option<C>
unsafe impl<C> Sync for CartableOptionPointer<C> where C: Send + CartablePointerLike {}
#[cfg(test)]
mod tests {
use super::*;
use crate::Yoke;
use core::mem::size_of;
const SAMPLE_BYTES: &[u8] = b"abCDEfg";
const W: usize = size_of::<usize>();
#[test]
fn test_sizes() {
assert_eq!(W * 4, size_of::<Yoke<[usize; 3], &&[u8]>>());
assert_eq!(W * 4, size_of::<Yoke<[usize; 3], Option<&&[u8]>>>());
assert_eq!(
W * 4,
size_of::<Yoke<[usize; 3], CartableOptionPointer<&&[u8]>>>()
);
assert_eq!(W * 4, size_of::<Option<Yoke<[usize; 3], &&[u8]>>>());
assert_eq!(W * 5, size_of::<Option<Yoke<[usize; 3], Option<&&[u8]>>>>());
assert_eq!(
W * 4,
size_of::<Option<Yoke<[usize; 3], CartableOptionPointer<&&[u8]>>>>()
);
}
#[test]
fn test_new_sentinel() {
let start = DROP_INVOCATIONS.with(Cell::get);
{
let _ = CartableOptionPointer::<Rc<&[u8]>>::none();
}
assert_eq!(start, DROP_INVOCATIONS.with(Cell::get));
{
let _ = CartableOptionPointer::<Rc<&[u8]>>::none();
}
assert_eq!(start, DROP_INVOCATIONS.with(Cell::get));
}
#[test]
fn test_new_rc() {
let start = DROP_INVOCATIONS.with(Cell::get);
{
let _ = CartableOptionPointer::<Rc<&[u8]>>::from_cartable(SAMPLE_BYTES.into());
}
assert_eq!(start + 1, DROP_INVOCATIONS.with(Cell::get));
}
#[test]
fn test_rc_clone() {
let start = DROP_INVOCATIONS.with(Cell::get);
{
let x = CartableOptionPointer::<Rc<&[u8]>>::from_cartable(SAMPLE_BYTES.into());
assert_eq!(start, DROP_INVOCATIONS.with(Cell::get));
{
let _ = x.clone();
}
assert_eq!(start, DROP_INVOCATIONS.with(Cell::get));
{
let _ = x.clone();
let _ = x.clone();
let _ = x.clone();
}
assert_eq!(start, DROP_INVOCATIONS.with(Cell::get));
}
assert_eq!(start + 1, DROP_INVOCATIONS.with(Cell::get));
}
}

88
vendor/yoke/src/either.rs vendored Normal file
View File

@@ -0,0 +1,88 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
//! Types to enable polymorphic carts.
use crate::CloneableCart;
use core::ops::Deref;
use stable_deref_trait::StableDeref;
/// A cart that can be one type or the other. Enables ergonomic polymorphic carts.
///
/// `EitherCart` enables yokes originating from different data sources and therefore
/// having different cart types to be merged into the same yoke type, but still being
/// able to recover the original cart type if necessary.
///
/// All relevant Cart traits are implemented for `EitherCart`, and carts can be
/// safely wrapped in an `EitherCart`.
///
/// Also see [`Yoke::erase_box_cart()`](crate::Yoke::erase_box_cart).
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
/// use yoke::either::EitherCart;
/// use yoke::Yoke;
///
/// let y1: Yoke<&'static str, Rc<str>> =
/// Yoke::attach_to_zero_copy_cart("reference counted hello world".into());
///
/// let y2: Yoke<&'static str, &str> = Yoke::attach_to_zero_copy_cart("borrowed hello world");
///
/// type CombinedYoke<'a> = Yoke<&'static str, EitherCart<Rc<str>, &'a str>>;
///
/// // Both yokes can be combined into a single yoke type despite different carts
/// let y3: CombinedYoke = y1.wrap_cart_in_either_a();
/// let y4: CombinedYoke = y2.wrap_cart_in_either_b();
///
/// assert_eq!(*y3.get(), "reference counted hello world");
/// assert_eq!(*y4.get(), "borrowed hello world");
///
/// // The resulting yoke is cloneable if both cart types implement CloneableCart
/// let y5 = y4.clone();
/// assert_eq!(*y5.get(), "borrowed hello world");
/// ```
#[derive(Clone, PartialEq, Eq, Debug)]
#[allow(clippy::exhaustive_enums)] // stable
pub enum EitherCart<C0, C1> {
A(C0),
B(C1),
}
impl<C0, C1, T> Deref for EitherCart<C0, C1>
where
C0: Deref<Target = T>,
C1: Deref<Target = T>,
T: ?Sized,
{
type Target = T;
fn deref(&self) -> &T {
use EitherCart::*;
match self {
A(a) => a.deref(),
B(b) => b.deref(),
}
}
}
// Safety: Safe because both sub-types implement the trait.
unsafe impl<C0, C1, T> StableDeref for EitherCart<C0, C1>
where
C0: StableDeref,
C1: StableDeref,
C0: Deref<Target = T>,
C1: Deref<Target = T>,
T: ?Sized,
{
}
// Safety: Safe because both sub-types implement the trait.
unsafe impl<C0, C1> CloneableCart for EitherCart<C0, C1>
where
C0: CloneableCart,
C1: CloneableCart,
{
}

41
vendor/yoke/src/erased.rs vendored Normal file
View File

@@ -0,0 +1,41 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
//! This module contains helper types for erasing Cart types.
//!
//! See the docs of [`Yoke::erase_rc_cart()`](crate::Yoke::erase_rc_cart)
//! and [`Yoke::erase_box_cart()`](crate::Yoke::erase_box_cart) for more info.
//!
//! ✨ *Enabled with the `alloc` Cargo feature.*
use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::sync::Arc;
/// Dummy trait that lets us `dyn Drop`
///
/// `dyn Drop` isn't legal (and doesn't make sense since `Drop` is not
/// implement on all destructible types). However, all trait objects come with
/// a destructor, so we can just use an empty trait to get a destructor object.
pub trait ErasedDestructor: 'static {}
impl<T: 'static> ErasedDestructor for T {}
/// A type-erased Cart that has `Arc` semantics
///
/// See the docs of [`Yoke::erase_arc_cart()`](crate::Yoke::erase_rc_cart) for more info.
///
/// ✨ *Enabled with the `alloc` Cargo feature.*
pub type ErasedArcCart = Arc<dyn ErasedDestructor + Send + Sync>;
/// A type-erased Cart that has `Rc` semantics
///
/// See the docs of [`Yoke::erase_rc_cart()`](crate::Yoke::erase_rc_cart) for more info.
///
/// ✨ *Enabled with the `alloc` Cargo feature.*
pub type ErasedRcCart = Rc<dyn ErasedDestructor>;
/// A type-erased Cart that has `Box` semantics
///
/// See the docs of [`Yoke::erase_box_cart()`](crate::Yoke::erase_box_cart) for more info.
///
/// ✨ *Enabled with the `alloc` Cargo feature.*
pub type ErasedBoxCart = Box<dyn ErasedDestructor>;

95
vendor/yoke/src/kinda_sorta_dangling.rs vendored Normal file
View File

@@ -0,0 +1,95 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
use core::mem::{ManuallyDrop, MaybeUninit};
use core::ops::{Deref, DerefMut};
/// This type is intended to be similar to the type `MaybeDangling<T>`
/// proposed in [RFC 3336].
///
/// The effect of this is that in Rust's safety model, types inside here are not
/// expected to have any memory dependent validity properties (`dereferenceable`, `noalias`).
///
/// See [#3696] for a testcase where `Yoke` fails under miri's field-retagging mode if not using
/// KindaSortaDangling.
///
/// This has `T: 'static` since we don't need anything
/// else and we don't want to have to think (more) about variance over lifetimes or dropck.
///
/// After [RFC 3336] lands we can use `MaybeDangling` instead.
///
/// Note that a version of this type also exists publicly as the [`maybe_dangling`]
/// crate; which also exports a patched `ManuallyDrop` with similar semantics and
/// does not require `T: 'static`. Consider using this if you need something more general
/// and are okay with adding dependencies.
///
/// [RFC 3336]: https://github.com/rust-lang/rfcs/pull/3336
/// [#3696]: https://github.com/unicode-org/icu4x/issues/3696
/// [`maybe_dangling`](https://docs.rs/maybe-dangling/0.1.0/maybe_dangling/struct.MaybeDangling.html)
#[repr(transparent)]
pub(crate) struct KindaSortaDangling<T: 'static> {
/// Safety invariant: This is always an initialized T, never uninit or other
/// invalid bit patterns. Its drop glue will execute during Drop::drop rather than
/// during the drop glue for KindaSortaDangling, which means that we have to be careful about
/// not touching the values as initialized during `drop` after that, but that's a short period of time.
dangle: MaybeUninit<T>,
}
impl<T: 'static> KindaSortaDangling<T> {
#[inline]
pub(crate) const fn new(dangle: T) -> Self {
KindaSortaDangling {
dangle: MaybeUninit::new(dangle),
}
}
#[inline]
pub(crate) fn into_inner(self) -> T {
// Self has a destructor, we want to avoid having it be called
let manual = ManuallyDrop::new(self);
// Safety:
// We can call assume_init_read() due to the library invariant on this type,
// however since it is a read() we must be careful about data duplication.
// The only code using `self` after this is the drop glue, which we have disabled via
// the ManuallyDrop.
unsafe { manual.dangle.assume_init_read() }
}
}
impl<T: 'static> Deref for KindaSortaDangling<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
// Safety: Due to the safety invariant on `dangle`, it is guaranteed to be always
// initialized as deref is never called during drop.
unsafe { self.dangle.assume_init_ref() }
}
}
impl<T: 'static> DerefMut for KindaSortaDangling<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
// Safety: Due to the safety invariant on `dangle`, it is guaranteed to be always
// initialized as deref_mut is never called during drop.
unsafe { self.dangle.assume_init_mut() }
}
}
impl<T: 'static> Drop for KindaSortaDangling<T> {
#[inline]
fn drop(&mut self) {
// Safety: We are reading and dropping a valid initialized T.
//
// As `drop_in_place()` is a `read()`-like duplication operation we must be careful that the original value isn't
// used afterwards. It won't be because this is drop and the only
// code that will run after this is `self`'s drop glue, and that drop glue is empty
// because MaybeUninit has no drop.
//
// We use `drop_in_place()` instead of `let _ = ... .assume_init_read()` to avoid creating a move
// of the inner `T` (without `KindaSortaDangling` protection!) type into a local -- we don't want to
// assert any of `T`'s memory-related validity properties here.
unsafe {
self.dangle.as_mut_ptr().drop_in_place();
}
}
}

68
vendor/yoke/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,68 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
//! This crate provides [`Yoke<Y, C>`][Yoke], which allows one to "yoke" (attach) a zero-copy deserialized
//! object (say, a [`Cow<'a, str>`](alloc::borrow::Cow)) to the source it was deserialized from, (say, an [`Rc<[u8]>`](alloc::rc::Rc)),
//! known in this crate as a "cart", producing a type that looks like `Yoke<Cow<'static, str>, Rc<[u8]>>`
//! and can be moved around with impunity.
//!
//! Succinctly, this allows one to "erase" static lifetimes and turn them into dynamic ones, similarly
//! to how `dyn` allows one to "erase" static types and turn them into dynamic ones.
//!
//! Most of the time the yokeable `Y` type will be some kind of zero-copy deserializable
//! abstraction, potentially with an owned variant (like [`Cow`](alloc::borrow::Cow),
//! [`ZeroVec`](https://docs.rs/zerovec), or an aggregate containing such types), and the cart `C` will be some smart pointer like
//! [`Box<T>`](alloc::boxed::Box), [`Rc<T>`](alloc::rc::Rc), or [`Arc<T>`](std::sync::Arc), potentially wrapped in an [`Option<T>`](Option).
//!
//! The key behind this crate is [`Yoke::get()`], where calling [`.get()`][Yoke::get] on a type like
//! `Yoke<Cow<'static, str>, _>` will get you a short-lived `&'a Cow<'a, str>`, restricted to the
//! lifetime of the borrow used during [`.get()`](Yoke::get). This is entirely safe since the `Cow` borrows from
//! the cart type `C`, which cannot be interfered with as long as the `Yoke` is borrowed by [`.get()`](Yoke::get).
//! [`.get()`](Yoke::get) protects access by essentially reifying the erased lifetime to a safe local one
//! when necessary.
//!
//! See the documentation of [`Yoke`] for more details.
// https://github.com/unicode-org/icu4x/blob/main/documents/process/boilerplate.md#library-annotations
#![cfg_attr(not(any(test, doc)), no_std)]
#![cfg_attr(
not(test),
deny(
clippy::indexing_slicing,
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::exhaustive_structs,
clippy::exhaustive_enums,
clippy::trivially_copy_pass_by_ref,
missing_debug_implementations,
)
)]
// The lifetimes here are important for safety and explicitly writing
// them out is good even when redundant
#![allow(clippy::needless_lifetimes)]
#[cfg(feature = "alloc")]
extern crate alloc;
pub mod cartable_ptr;
pub mod either;
#[cfg(feature = "alloc")]
pub mod erased;
mod kinda_sorta_dangling;
mod macro_impls;
mod utils;
mod yoke;
mod yokeable;
#[cfg(feature = "zerofrom")]
mod zero_from;
#[cfg(feature = "derive")]
pub use yoke_derive::Yokeable;
pub use crate::yoke::{CloneableCart, Yoke};
pub use crate::yokeable::Yokeable;
#[cfg(feature = "zerofrom")]
use zerofrom::ZeroFrom;

128
vendor/yoke/src/macro_impls.rs vendored Normal file
View File

@@ -0,0 +1,128 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
// In this case consistency between impls is more important
// than using pointer casts
#![allow(clippy::transmute_ptr_to_ptr)]
use crate::Yokeable;
use core::{
mem::{self, ManuallyDrop},
ptr,
};
macro_rules! copy_yoke_impl {
() => {
#[inline]
fn transform(&self) -> &Self::Output {
self
}
#[inline]
fn transform_owned(self) -> Self::Output {
self
}
#[inline]
unsafe fn make(this: Self::Output) -> Self {
this
}
#[inline]
fn transform_mut<F>(&'a mut self, f: F)
where
F: 'static + for<'b> FnOnce(&'b mut Self::Output),
{
f(self)
}
};
}
macro_rules! impl_copy_type {
($ty:ty) => {
// Safety: all the types that this macro is used to generate impls of Yokeable for do not
// borrow any memory.
unsafe impl<'a> Yokeable<'a> for $ty {
type Output = Self;
copy_yoke_impl!();
}
};
}
impl_copy_type!(());
impl_copy_type!(u8);
impl_copy_type!(u16);
impl_copy_type!(u32);
impl_copy_type!(u64);
impl_copy_type!(u128);
impl_copy_type!(usize);
impl_copy_type!(i8);
impl_copy_type!(i16);
impl_copy_type!(i32);
impl_copy_type!(i64);
impl_copy_type!(i128);
impl_copy_type!(isize);
impl_copy_type!(char);
impl_copy_type!(bool);
// This is for when we're implementing Yoke on a complex type such that it's not
// obvious to the compiler that the lifetime is covariant
//
// Safety: the caller of this macro must ensure that `Self` is indeed covariant in 'a.
macro_rules! unsafe_complex_yoke_impl {
() => {
fn transform(&'a self) -> &'a Self::Output {
// Safety: equivalent to casting the lifetime. Macro caller ensures covariance.
unsafe { mem::transmute(self) }
}
fn transform_owned(self) -> Self::Output {
debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
// Safety: equivalent to casting the lifetime. Macro caller ensures covariance.
unsafe {
let ptr: *const Self::Output = (&self as *const Self).cast();
let _ = ManuallyDrop::new(self);
ptr::read(ptr)
}
}
unsafe fn make(from: Self::Output) -> Self {
debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
let ptr: *const Self = (&from as *const Self::Output).cast();
let _ = ManuallyDrop::new(from);
// Safety: `ptr` is certainly valid, aligned and points to a properly initialized value, as
// it comes from a value that was moved into a ManuallyDrop.
unsafe { ptr::read(ptr) }
}
fn transform_mut<F>(&'a mut self, f: F)
where
F: 'static + for<'b> FnOnce(&'b mut Self::Output),
{
// Cast away the lifetime of Self
// Safety: this is equivalent to f(transmute(self)), and the documentation of the trait
// method explains why doing so is sound.
unsafe { f(mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) }
}
};
}
// Safety: since T implements Yokeable<'a>, Option<T<'b>> must be covariant on 'b or the Yokeable
// implementation on T would be unsound.
unsafe impl<'a, T: 'static + for<'b> Yokeable<'b>> Yokeable<'a> for Option<T> {
type Output = Option<<T as Yokeable<'a>>::Output>;
unsafe_complex_yoke_impl!();
}
// Safety: since T1, T2 implement Yokeable<'a>, (T1<'b>, T2<'b>) must be covariant on 'b or the Yokeable
// implementation on T would be unsound.
unsafe impl<'a, T1: 'static + for<'b> Yokeable<'b>, T2: 'static + for<'b> Yokeable<'b>> Yokeable<'a>
for (T1, T2)
{
type Output = (<T1 as Yokeable<'a>>::Output, <T2 as Yokeable<'a>>::Output);
unsafe_complex_yoke_impl!();
}
// Safety: since T implements Yokeable<'a>, [T<'b>; N] must be covariant on 'b or the Yokeable
// implementation on T would be unsound.
unsafe impl<'a, T: 'static + for<'b> Yokeable<'b>, const N: usize> Yokeable<'a> for [T; N] {
type Output = [<T as Yokeable<'a>>::Output; N];
unsafe_complex_yoke_impl!();
}

25
vendor/yoke/src/utils.rs vendored Normal file
View File

@@ -0,0 +1,25 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
use crate::Yokeable;
use core::mem;
/// This method casts `yokeable` between `&'a mut Y<'static>` and `&'a mut Y<'a>`,
/// and passes it to `f`.
///
/// See [`Yokeable::transform_mut`] for why this is safe, noting that no `'static` return type
/// can leak data from the cart or Yokeable.
#[inline]
pub(crate) fn transform_mut_yokeable<'a, Y, F, R>(yokeable: &'a mut Y, f: F) -> R
where
Y: Yokeable<'a>,
// be VERY CAREFUL changing this signature, it is very nuanced
F: 'static + for<'b> FnOnce(&'b mut Y::Output) -> R,
R: 'static,
{
// Cast away the lifetime of `Y`
// Safety: this is equivalent to f(transmute(yokeable)), and the documentation of
// [`Yokeable::transform_mut`] and this function explain why doing so is sound.
unsafe { f(mem::transmute::<&'a mut Y, &'a mut Y::Output>(yokeable)) }
}

2065
vendor/yoke/src/yoke.rs vendored Normal file

File diff suppressed because it is too large Load Diff

360
vendor/yoke/src/yokeable.rs vendored Normal file
View File

@@ -0,0 +1,360 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
#[cfg(feature = "alloc")]
use alloc::borrow::{Cow, ToOwned};
use core::{marker::PhantomData, mem};
/// The `Yokeable<'a>` trait is implemented on the `'static` version of any zero-copy type; for
/// example, `Cow<'static, T>` implements `Yokeable<'a>` (for all `'a`).
///
/// One can use
/// `Yokeable::Output` on this trait to obtain the "lifetime'd" value of the `Cow<'static, T>`,
/// e.g. `<Cow<'static, T> as Yokeable<'a>'>::Output` is `Cow<'a, T>`.
///
/// A [`Yokeable`] type is essentially one with a covariant lifetime parameter,
/// matched to the parameter in the trait definition. The trait allows one to cast
/// the covariant lifetime to and from `'static`.
///
/// **Most of the time, if you need to implement [`Yokeable`], you should be able to use the safe
/// [`#[derive(Yokeable)]`](yoke_derive::Yokeable) custom derive.**
///
/// While Rust does not yet have GAT syntax, for the purpose of this documentation
/// we shall refer to "`Self` with a lifetime `'a`" with the syntax `Self<'a>`.
/// Self<'static> is a stand-in for the HKT Self<'_>: lifetime -> type.
///
/// With this terminology, [`Yokeable`] exposes ways to cast between `Self<'static>` and `Self<'a>` generically.
/// This is useful for turning covariant lifetimes to _dynamic_ lifetimes, where `'static` is
/// used as a way to "erase" the lifetime.
///
/// # Safety
///
/// This trait is safe to implement on types with a _covariant_ lifetime parameter, i.e. one where
/// [`Self::transform()`]'s body can simply be `{ self }`. This will occur when the lifetime
/// parameter is used within references, but not in the arguments of function pointers or in mutable
/// positions (either in `&mut` or via interior mutability)
///
/// This trait must be implemented on the `'static` version of such a type, e.g. one should
/// implement `Yokeable<'a>` (for all `'a`) on `Cow<'static, T>`.
///
/// This trait is also safe to implement on types that do not borrow memory.
///
/// There are further constraints on implementation safety on individual methods.
///
/// # Implementation example
///
/// Implementing this trait manually is unsafe. Where possible, you should use the safe
/// [`#[derive(Yokeable)]`](yoke_derive::Yokeable) custom derive instead. We include an example
/// in case you have your own zero-copy abstractions you wish to make yokeable.
///
/// ```rust
/// # use yoke::Yokeable;
/// # use std::borrow::Cow;
/// # use std::{mem, ptr};
/// struct Bar<'a> {
/// numbers: Cow<'a, [u8]>,
/// string: Cow<'a, str>,
/// owned: Vec<u8>,
/// }
///
/// unsafe impl<'a> Yokeable<'a> for Bar<'static> {
/// type Output = Bar<'a>;
/// fn transform(&'a self) -> &'a Bar<'a> {
/// // covariant lifetime cast, can be done safely
/// self
/// }
///
/// fn transform_owned(self) -> Bar<'a> {
/// // covariant lifetime cast, can be done safely
/// self
/// }
///
/// unsafe fn make(from: Bar<'a>) -> Self {
/// unsafe { mem::transmute(from) }
/// }
///
/// fn transform_mut<F>(&'a mut self, f: F)
/// where
/// F: 'static + FnOnce(&'a mut Self::Output),
/// {
/// unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
/// }
/// }
/// ```
pub unsafe trait Yokeable<'a>: 'static {
/// This type MUST be `Self` with the `'static` replaced with `'a`, i.e. `Self<'a>`
type Output: 'a;
/// This method must cast `self` between `&'a Self<'static>` and `&'a Self<'a>`.
///
/// # Implementation safety
///
/// If the invariants of [`Yokeable`] are being satisfied, the body of this method
/// should simply be `{ self }`, though it's acceptable to include additional assertions
/// if desired.
fn transform(&'a self) -> &'a Self::Output;
/// This method must cast `self` between `Self<'static>` and `Self<'a>`.
///
/// # Implementation safety
///
/// If the invariants of [`Yokeable`] are being satisfied, the body of this method
/// should simply be `{ self }`, though it's acceptable to include additional assertions
/// if desired.
fn transform_owned(self) -> Self::Output;
/// This method can be used to cast away `Self<'a>`'s lifetime.
///
/// # Safety
///
/// The returned value must be destroyed before the data `from` was borrowing from is.
///
/// # Implementation safety
///
/// A safe implementation of this method must be equivalent to a transmute between
/// `Self<'a>` and `Self<'static>`
unsafe fn make(from: Self::Output) -> Self;
/// This method must cast `self` between `&'a mut Self<'static>` and `&'a mut Self<'a>`,
/// and pass it to `f`.
///
/// # Implementation safety
///
/// A safe implementation of this method must be equivalent to a pointer cast/transmute between
/// `&mut Self<'a>` and `&mut Self<'static>` being passed to `f`
///
/// # Why is this safe?
///
/// Typically covariant lifetimes become invariant when hidden behind an `&mut`,
/// which is why the implementation of this method cannot just be `f(self)`.
/// The reason behind this is that while _reading_ a covariant lifetime that has been cast to a shorter
/// one is always safe (this is roughly the definition of a covariant lifetime), writing
/// may not necessarily be safe since you could write a smaller reference to it. For example,
/// the following code is unsound because it manages to stuff a `'a` lifetime into a `Cow<'static>`
///
/// ```rust,compile_fail
/// # use std::borrow::Cow;
/// # use yoke::Yokeable;
/// struct Foo {
/// str: String,
/// cow: Cow<'static, str>,
/// }
///
/// fn unsound<'a>(foo: &'a mut Foo) {
/// let a: &str = &foo.str;
/// foo.cow.transform_mut(|cow| *cow = Cow::Borrowed(a));
/// }
/// ```
///
/// However, this code will not compile because [`Yokeable::transform_mut()`] requires `F: 'static`.
/// This enforces that while `F` may mutate `Self<'a>`, it can only mutate it in a way that does
/// not insert additional references. For example, `F` may call `to_owned()` on a `Cow` and mutate it,
/// but it cannot insert a new _borrowed_ reference because it has nowhere to borrow _from_ --
/// `f` does not contain any borrowed references, and while we give it `Self<'a>` (which contains borrowed
/// data), that borrowed data is known to be valid
///
/// Note that the `for<'b>` is also necessary, otherwise the following code would compile:
///
/// ```rust,compile_fail
/// # use std::borrow::Cow;
/// # use yoke::Yokeable;
/// # use std::mem;
/// #
/// // also safely implements Yokeable<'a>
/// struct Bar<'a> {
/// num: u8,
/// cow: Cow<'a, u8>,
/// }
///
/// fn unsound<'a>(bar: &'a mut Bar<'static>) {
/// bar.transform_mut(move |bar| bar.cow = Cow::Borrowed(&bar.num));
/// }
/// #
/// # unsafe impl<'a> Yokeable<'a> for Bar<'static> {
/// # type Output = Bar<'a>;
/// # fn transform(&'a self) -> &'a Bar<'a> {
/// # self
/// # }
/// #
/// # fn transform_owned(self) -> Bar<'a> {
/// # // covariant lifetime cast, can be done safely
/// # self
/// # }
/// #
/// # unsafe fn make(from: Bar<'a>) -> Self {
/// # let ret = mem::transmute_copy(&from);
/// # mem::forget(from);
/// # ret
/// # }
/// #
/// # fn transform_mut<F>(&'a mut self, f: F)
/// # where
/// # F: 'static + FnOnce(&'a mut Self::Output),
/// # {
/// # unsafe { f(mem::transmute(self)) }
/// # }
/// # }
/// ```
///
/// which is unsound because `bar` could be moved later, and we do not want to be able to
/// self-insert references to it.
///
/// The `for<'b>` enforces this by stopping the author of the closure from matching up the input
/// `&'b Self::Output` lifetime with `'a` and borrowing directly from it.
///
/// Thus the only types of mutations allowed are ones that move around already-borrowed data, or
/// introduce new owned data:
///
/// ```rust
/// # use std::borrow::Cow;
/// # use yoke::Yokeable;
/// struct Foo {
/// str: String,
/// cow: Cow<'static, str>,
/// }
///
/// fn sound(foo: &mut Foo) {
/// foo.cow.transform_mut(move |cow| cow.to_mut().push('a'));
/// }
/// ```
///
/// More formally, a reference to an object that `f` assigns to a reference
/// in Self<'a> could be obtained from:
/// - a local variable: the compiler rejects the assignment because 'a certainly
/// outlives local variables in f.
/// - a field in its argument: because of the for<'b> bound, the call to `f`
/// must be valid for a particular 'b that is strictly shorter than 'a. Thus,
/// the compiler rejects the assignment.
/// - a reference field in Self<'a>: this does not extend the set of
/// non-static lifetimes reachable from Self<'a>, so this is fine.
/// - one of f's captures: since F: 'static, the resulting reference must refer
/// to 'static data.
/// - a static or thread_local variable: ditto.
fn transform_mut<F>(&'a mut self, f: F)
where
// be VERY CAREFUL changing this signature, it is very nuanced (see above)
F: 'static + for<'b> FnOnce(&'b mut Self::Output);
}
#[cfg(feature = "alloc")]
// Safety: Cow<'a, _> is covariant in 'a.
unsafe impl<'a, T: 'static + ToOwned + ?Sized> Yokeable<'a> for Cow<'static, T>
where
<T as ToOwned>::Owned: Sized,
{
type Output = Cow<'a, T>;
#[inline]
fn transform(&'a self) -> &'a Cow<'a, T> {
// Doesn't need unsafe: `'a` is covariant so this lifetime cast is always safe
self
}
#[inline]
fn transform_owned(self) -> Cow<'a, T> {
// Doesn't need unsafe: `'a` is covariant so this lifetime cast is always safe
self
}
#[inline]
unsafe fn make(from: Cow<'a, T>) -> Self {
// i hate this
// unfortunately Rust doesn't think `mem::transmute` is possible since it's not sure the sizes
// are the same
debug_assert!(mem::size_of::<Cow<'a, T>>() == mem::size_of::<Self>());
let ptr: *const Self = (&from as *const Self::Output).cast();
let _ = core::mem::ManuallyDrop::new(from);
// Safety: `ptr` is certainly valid, aligned and points to a properly initialized value, as
// it comes from a value that was moved into a ManuallyDrop.
unsafe { core::ptr::read(ptr) }
}
#[inline]
fn transform_mut<F>(&'a mut self, f: F)
where
F: 'static + for<'b> FnOnce(&'b mut Self::Output),
{
// Cast away the lifetime of Self
// Safety: this is equivalent to f(transmute(self)), and the documentation of the trait
// method explains why doing so is sound.
unsafe { f(mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) }
}
}
// Safety: &'a T is covariant in 'a.
unsafe impl<'a, T: 'static + ?Sized> Yokeable<'a> for &'static T {
type Output = &'a T;
#[inline]
fn transform(&'a self) -> &'a &'a T {
// Doesn't need unsafe: `'a` is covariant so this lifetime cast is always safe
self
}
#[inline]
fn transform_owned(self) -> &'a T {
// Doesn't need unsafe: `'a` is covariant so this lifetime cast is always safe
self
}
#[inline]
unsafe fn make(from: &'a T) -> Self {
// Safety: function safety invariant guarantees that the returned reference
// will never be used beyond its original lifetime.
unsafe { mem::transmute(from) }
}
#[inline]
fn transform_mut<F>(&'a mut self, f: F)
where
F: 'static + for<'b> FnOnce(&'b mut Self::Output),
{
// Cast away the lifetime of Self
// Safety: this is equivalent to f(transmute(self)), and the documentation of the trait
// method explains why doing so is sound.
unsafe { f(mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) }
}
}
#[cfg(feature = "alloc")]
// Safety: Vec<T: 'static> never borrows.
unsafe impl<'a, T: 'static> Yokeable<'a> for alloc::vec::Vec<T> {
type Output = alloc::vec::Vec<T>;
#[inline]
fn transform(&'a self) -> &'a alloc::vec::Vec<T> {
self
}
#[inline]
fn transform_owned(self) -> alloc::vec::Vec<T> {
self
}
#[inline]
unsafe fn make(from: alloc::vec::Vec<T>) -> Self {
from
}
#[inline]
fn transform_mut<F>(&'a mut self, f: F)
where
F: 'static + for<'b> FnOnce(&'b mut Self::Output),
{
f(self)
}
}
// Safety: PhantomData is a ZST.
unsafe impl<'a, T: ?Sized + 'static> Yokeable<'a> for PhantomData<T> {
type Output = PhantomData<T>;
fn transform(&'a self) -> &'a Self::Output {
self
}
fn transform_owned(self) -> Self::Output {
self
}
unsafe fn make(from: Self::Output) -> Self {
from
}
fn transform_mut<F>(&'a mut self, f: F)
where
// be VERY CAREFUL changing this signature, it is very nuanced (see above)
F: 'static + for<'b> FnOnce(&'b mut Self::Output),
{
f(self)
}
}

44
vendor/yoke/src/zero_from.rs vendored Normal file
View File

@@ -0,0 +1,44 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
use crate::Yoke;
use crate::Yokeable;
use core::ops::Deref;
use stable_deref_trait::StableDeref;
use crate::ZeroFrom;
impl<Y, C> Yoke<Y, C>
where
Y: for<'a> Yokeable<'a>,
for<'a> <Y as Yokeable<'a>>::Output: ZeroFrom<'a, <C as Deref>::Target>,
C: StableDeref + Deref,
<C as Deref>::Target: 'static,
{
/// Construct a [`Yoke`]`<Y, C>` from a cart implementing `StableDeref` by zero-copy cloning
/// the cart to `Y` and then yokeing that object to the cart.
///
/// The type `Y` must implement [`ZeroFrom`]`<C::Target>`. This trait is auto-implemented
/// on many common types and can be custom implemented or derived in order to make it easier
/// to construct a `Yoke`.
///
/// # Example
///
/// Attach to a cart:
///
/// ```
/// use std::borrow::Cow;
/// use yoke::Yoke;
///
/// let yoke = Yoke::<Cow<'static, str>, String>::attach_to_zero_copy_cart(
/// "demo".to_owned(),
/// );
///
/// assert_eq!("demo", yoke.get());
/// ```
pub fn attach_to_zero_copy_cart(cart: C) -> Self {
Yoke::<Y, C>::attach_to_cart(cart, |c| <Y as Yokeable>::Output::zero_from(c))
}
}

83
vendor/yoke/tests/bincode.rs vendored Normal file
View File

@@ -0,0 +1,83 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
// This test is a duplicate of one of the doctests, but is written separately
// since `cargo miri test` doesn't work on doctests yet
use std::borrow::Cow;
use std::mem;
use std::rc::Rc;
use yoke::{Yoke, Yokeable};
fn load_from_cache(_filename: &str) -> Rc<[u8]> {
// dummy implementation
Rc::new([0x5, 0, 0, 0, 0, 0, 0, 0, 0x68, 0x65, 0x6c, 0x6c, 0x6f])
}
fn load_object(filename: &str) -> Yoke<Bar<'static>, Rc<[u8]>> {
let rc: Rc<[u8]> = load_from_cache(filename);
Yoke::<Bar<'static>, Rc<[u8]>>::attach_to_cart(rc, |data: &[u8]| {
// A real implementation would properly deserialize `Bar` as a whole
Bar {
numbers: Cow::Borrowed(bincode::deserialize(data).unwrap()),
string: Cow::Borrowed(bincode::deserialize(data).unwrap()),
owned: Vec::new(),
}
})
}
// also implements Yokeable
struct Bar<'a> {
numbers: Cow<'a, [u8]>,
string: Cow<'a, str>,
owned: Vec<u8>,
}
unsafe impl<'a> Yokeable<'a> for Bar<'static> {
type Output = Bar<'a>;
#[inline]
fn transform(&'a self) -> &'a Bar<'a> {
self
}
#[inline]
fn transform_owned(self) -> Bar<'a> {
self
}
#[inline]
unsafe fn make(from: Bar<'a>) -> Self {
let ret = mem::transmute_copy(&from);
mem::forget(from);
ret
}
#[inline]
fn transform_mut<F>(&'a mut self, f: F)
where
F: 'static + FnOnce(&'a mut Self::Output),
{
unsafe { f(mem::transmute::<&mut Bar<'_>, &mut Bar<'a>>(self)) }
}
}
#[test]
fn test_load() {
// `load_object()` deserializes an object from a file
let mut bar = load_object("filename.bincode");
assert_eq!(bar.get().string, "hello");
assert!(matches!(bar.get().string, Cow::Borrowed(_)));
assert_eq!(&*bar.get().numbers, &[0x68, 0x65, 0x6c, 0x6c, 0x6f]);
assert!(matches!(bar.get().numbers, Cow::Borrowed(_)));
assert_eq!(&*bar.get().owned, &[]);
bar.with_mut(|bar| {
bar.string.to_mut().push_str(" world");
bar.owned.extend_from_slice(&[1, 4, 1, 5, 9]);
});
assert_eq!(bar.get().string, "hello world");
assert!(matches!(bar.get().string, Cow::Owned(_)));
assert_eq!(&*bar.get().owned, &[1, 4, 1, 5, 9]);
// Unchanged and still Cow::Borrowed
assert_eq!(&*bar.get().numbers, &[0x68, 0x65, 0x6c, 0x6c, 0x6f]);
assert!(matches!(bar.get().numbers, Cow::Borrowed(_)));
}

15
vendor/yoke/tests/miri.rs vendored Normal file
View File

@@ -0,0 +1,15 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
use yoke::Yoke;
// Test for strong protection, should pass under miri with -Zmiri-retag-fields
// See https://github.com/unicode-org/icu4x/issues/3696
fn example(_: Yoke<&'static [u8], Vec<u8>>) {}
#[test]
fn run_test() {
example(Yoke::attach_to_cart(vec![0, 1, 2], |data| data));
}