1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
#![unstable(feature = "ptr_metadata", issue = "81513")]

use crate::fmt;
use crate::hash::{Hash, Hasher};

/// 提供任何指向类型的指针元数据类型。
///
/// # 指针元数据
///
/// Rust 中的裸指针类型和引用类型可以认为是由两部分组成:
/// 包含该值的内存地址和一些元数据的数据指针。
///
/// 对于静态大小的类型 (实现 `Sized` traits) 以及 `extern` 类型,指针被称为 `thin`: 元数据的大小为零,其类型为 `()`。
///
///
/// 指向 [动态大小的类型][dst] 的指针被称为 `wide` 或 `fat`,它们具有非零大小的元数据:
///
/// * 对于最后一个字段是 DST 的结构体,元数据是最后一个字段的元数据
/// * 对于 `str` 类型,元数据是 `usize` 的长度 (以字节为单位)
/// * 对于 `[T]` 之类的切片类型,元数据是 `usize` 中项的长度
/// * 对于 `dyn SomeTrait` 之类的 trait 对象,元数据为 [`DynMetadata<Self>`][DynMetadata] (例如 `DynMetadata<dyn SomeTrait>`)
///
/// 在 future 中,Rust 语言可能会获得具有不同指针元数据的新型类型。
///
/// [dst]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#dynamically-sized-types-dsts
///
/// # The `Pointee` trait
///
/// 这个 trait 的重点是它的 `Metadata` 关联类型,像上面讲的一样,它是 `()` 或 `usize` 或 `DynMetadata<_>`。
/// 它会针对每种类型自动实现。
/// 即使没有相应的限制,也可以假定它是在泛型上下文中实现的。
///
/// # Usage
///
/// 可以使用 [`to_raw_parts`] 方法将裸指针分解为数据地址和元数据组件。
///
/// 或者,可以使用 [`metadata`] 函数单独提取元数据。
/// 可以将引用传递给 [`metadata`] 并进行隐式强制。
///
/// 可以使用 [`from_raw_parts`] 或 [`from_raw_parts_mut`] 将 (possibly-wide) 指针从其地址和元数据放回原处。
///
/// [`to_raw_parts`]: *const::to_raw_parts
///
///
///
///
///
///
///
///
///
#[lang = "pointee_trait"]
#[rustc_deny_explicit_impl]
pub trait Pointee {
    /// 指针中的元数据类型,并引用 `Self`。
    #[lang = "metadata_type"]
    // NOTE: 保持 `library/core/src/ptr/metadata.rs` 中 `static_assert_expected_bounds_for_metadata` 中的 trait bounds 与此处的同步:
    //
    //
    type Metadata: Copy + Send + Sync + Ord + Hash + Unpin;
}

/// 实现此 trait 别名的类型的指针为 `thin`。
///
/// 这包括静态 `Sized` 类型和 `extern` 类型。
///
/// # Example
///
/// ```rust
/// #![feature(ptr_metadata)]
///
/// fn this_never_panics<T: std::ptr::Thin>() {
///     assert_eq!(std::mem::size_of::<&T>(), std::mem::size_of::<usize>())
/// }
/// ```
#[unstable(feature = "ptr_metadata", issue = "81513")]
// NOTE: 在 trait 别名在语言中稳定之前难道不能稳定它吗?
pub trait Thin = Pointee<Metadata = ()>;

/// 提取指针的元数据组件。
///
/// `*mut T`,`&T` 或 `&mut T` 类型的值可以隐式强制转换为 `*const T`,因此可以直接传递给此函数。
///
///
/// # Example
///
/// ```
/// #![feature(ptr_metadata)]
///
/// assert_eq!(std::ptr::metadata("foo"), 3_usize);
/// ```
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
#[inline]
pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
    // SAFETY: 因为 *const T 和 PtrComponents<T> 具有相同的内存布局,所以从 `PtrRepr` union 访问值是安全的。
    // 只有 std 可以做出此保证。
    //
    unsafe { PtrRepr { const_ptr: ptr }.components.metadata }
}

/// 根据数据地址和元数据形成 (possibly-wide) 裸指针。
///
/// 此函数是安全的,但是返回的指针对于解引用并不一定是安全的。
/// 对于切片,请参见 [`slice::from_raw_parts`] 的文档以了解安全要求。
/// 对于 trait 对象,元数据必须来自指向相同底层 erased 类型的指针。
///
/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
#[unstable(feature = "ptr_metadata", issue = "81513")]
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
#[inline]
pub const fn from_raw_parts<T: ?Sized>(
    data_address: *const (),
    metadata: <T as Pointee>::Metadata,
) -> *const T {
    // SAFETY: 因为 *const T 和 PtrComponents<T> 具有相同的内存布局,所以从 `PtrRepr` union 访问值是安全的。
    // 只有 std 可以做出此保证。
    //
    unsafe { PtrRepr { components: PtrComponents { data_address, metadata } }.const_ptr }
}

/// 执行与 [`from_raw_parts`] 相同的功能,除了返回原始 `*mut` 指针 (与原始 `*const` 指针相反) 之外。
///
///
/// 有关更多详细信息,请参见 [`from_raw_parts`] 的文档。
#[unstable(feature = "ptr_metadata", issue = "81513")]
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
#[inline]
pub const fn from_raw_parts_mut<T: ?Sized>(
    data_address: *mut (),
    metadata: <T as Pointee>::Metadata,
) -> *mut T {
    // SAFETY: 因为 *const T 和 PtrComponents<T> 具有相同的内存布局,所以从 `PtrRepr` union 访问值是安全的。
    // 只有 std 可以做出此保证。
    //
    unsafe { PtrRepr { components: PtrComponents { data_address, metadata } }.mut_ptr }
}

#[repr(C)]
union PtrRepr<T: ?Sized> {
    const_ptr: *const T,
    mut_ptr: *mut T,
    components: PtrComponents<T>,
}

#[repr(C)]
struct PtrComponents<T: ?Sized> {
    data_address: *const (),
    metadata: <T as Pointee>::Metadata,
}

// 需要避免 `T: Copy` 绑定的手动提示。
impl<T: ?Sized> Copy for PtrComponents<T> {}

// 需要避免 `T: Clone` 绑定的手动提示。
impl<T: ?Sized> Clone for PtrComponents<T> {
    fn clone(&self) -> Self {
        *self
    }
}

/// `Dyn = dyn SomeTrait` trait 对象类型的元数据。
///
/// 它是指向 vtable (虚拟调用表) 的指针,该表表示操作存储在 trait 对象内部的具体类型所需的所有信息。
/// 该 vtable 尤其包含:
///
/// * 类型大小
/// * 类型对齐
/// * 指向该类型的 `drop_in_place` impl 的指针 (对于纯旧数据,它可能是 no-op)
/// * 指向 trait 类型实现的所有方法的指针
///
/// 请注意,前三个是特殊的,因为它们是分配,丢弃和释放任何 trait 对象所必需的。
///
/// 可以使用不是 `dyn` trait 对象 (例如 `DynMetadata<u64>`) 的类型参数来命名此结构体,但不能获得该结构体的有意义的值。
///
///
///
///
#[lang = "dyn_metadata"]
pub struct DynMetadata<Dyn: ?Sized> {
    vtable_ptr: &'static VTable,
    phantom: crate::marker::PhantomData<Dyn>,
}

extern "C" {
    /// 用于访问 vtables 的不透明类型。
    ///
    /// `DynMetadata::size_of` 等的私有实现详细信息
    /// 在这个指针后面实际上没有任何抽象机内存。
    type VTable;
}

impl<Dyn: ?Sized> DynMetadata<Dyn> {
    /// 返回与此 vtable 关联的类型的大小。
    #[inline]
    pub fn size_of(self) -> usize {
        // 请注意,"存储在虚表中的大小" *不* 与 "size_of_val_raw 的结果" 相同。
        // 考虑像 `&(i32, dyn Send)` 这样的引用: vtable 将只存储 `Send` 部分的大小!
        //
        // SAFETY: DynMetadata 总是包含一个有效的 vtable 指针
        return unsafe {
            crate::intrinsics::vtable_size(self.vtable_ptr as *const VTable as *const ())
        };
    }

    /// 返回与此 vtable 关联的类型的对齐方式。
    #[inline]
    pub fn align_of(self) -> usize {
        // SAFETY: DynMetadata 总是包含一个有效的 vtable 指针
        return unsafe {
            crate::intrinsics::vtable_align(self.vtable_ptr as *const VTable as *const ())
        };
    }

    /// 将大小和对齐方式一起返回为 `Layout`
    #[inline]
    pub fn layout(self) -> crate::alloc::Layout {
        // SAFETY: 编译器针对特定的 Rust 类型发出此 vtable,已知该类型具有有效的布局。
        // 与 `Layout::for_value` 中的原理相同。
        unsafe { crate::alloc::Layout::from_size_align_unchecked(self.size_of(), self.align_of()) }
    }
}

unsafe impl<Dyn: ?Sized> Send for DynMetadata<Dyn> {}
unsafe impl<Dyn: ?Sized> Sync for DynMetadata<Dyn> {}

impl<Dyn: ?Sized> fmt::Debug for DynMetadata<Dyn> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("DynMetadata").field(&(self.vtable_ptr as *const VTable)).finish()
    }
}

// 避免 `Dyn: $Trait` 边界所需的手动提示。

impl<Dyn: ?Sized> Unpin for DynMetadata<Dyn> {}

impl<Dyn: ?Sized> Copy for DynMetadata<Dyn> {}

impl<Dyn: ?Sized> Clone for DynMetadata<Dyn> {
    #[inline]
    fn clone(&self) -> Self {
        *self
    }
}

impl<Dyn: ?Sized> Eq for DynMetadata<Dyn> {}

impl<Dyn: ?Sized> PartialEq for DynMetadata<Dyn> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        crate::ptr::eq::<VTable>(self.vtable_ptr, other.vtable_ptr)
    }
}

impl<Dyn: ?Sized> Ord for DynMetadata<Dyn> {
    #[inline]
    fn cmp(&self, other: &Self) -> crate::cmp::Ordering {
        (self.vtable_ptr as *const VTable).cmp(&(other.vtable_ptr as *const VTable))
    }
}

impl<Dyn: ?Sized> PartialOrd for DynMetadata<Dyn> {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<Dyn: ?Sized> Hash for DynMetadata<Dyn> {
    #[inline]
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        crate::ptr::hash::<VTable, _>(self.vtable_ptr, hasher)
    }
}