Skip to content

Commit

Permalink
跟随上游 PR #415 更新
Browse files Browse the repository at this point in the history
  • Loading branch information
PureWhiteWu committed Dec 17, 2023
1 parent 07674e3 commit a0607a9
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 77 deletions.
2 changes: 1 addition & 1 deletion src/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
>
> 如果大家对于翻译有更好的建议或者想法,欢迎直接 PR~
>
> 目前翻译基于 commit:83d015105e6d490fc30d6c95da1e56152a50e228,基于时间:2023/11/23
> 目前翻译基于 commit:f6bd083c4ccfc4ce6699b8b4154e3c45c5a27a8c,基于时间:2023/12/18
>
> Q:为什么不基于之前已有的中文版进行改进?
>
Expand Down
30 changes: 18 additions & 12 deletions src/phantom-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ impl<T> Drop for Vec<T> { /* … */ }
那么`impl<T> Drop for Vec<T>`这条语句会让 Rust 知道`Vec<T>`_拥有_`T`类型的值(更准确地说:可能会在`Drop`实现中使用`T`类型的值),那么当`Vec<T>`被 drop 的时候,Rust 就不会允许它们 _悬垂_

**添加一个额外的 `_owns_T: PhantomData<T>` 字段因此是*多余的*并且什么都不做**
当一个类型已经有了 `Drop impl` 时,**添加一个额外的 `_owns_T: PhantomData<T>` 字段是多余的,而且没有任何效果**,从 dropck(Drop 检查)的角度来看(它仍然会影响变量和自动特征)。

- (高级边缘情况:如果包含 `PhantomData` 的类型根本没有 `Drop` 实现,但仍然有 drop glue(通过拥有另一个带有 drop glue 的字段),那么这里提到的 dropck/`#[may_dangle]` 规则也同样适用:一个 `PhantomData<T>` 字段将要求 `T` 在包含类型作用域结束时可被丢弃)。

---

Expand Down Expand Up @@ -180,14 +182,18 @@ struct Vec<T> {
下面是一个关于所有可以使用`PhantomData`的神奇方式的表格:
(covariant:协变,invariant:不变,contravariant:逆变)

| Phantom type | `'a` | `T` | `Send` | `Sync` |
|-----------------------------|-----------|-----------------------------|-----------|-----------|
| `PhantomData<T>` | - | covariant (with drop check) | `T: Send` | `T: Sync` |
| `PhantomData<&'a T>` | covariant | covariant | `T: Sync` | `T: Sync` |
| `PhantomData<&'a mut T>` | covariant | invariant | `T: Send` | `T: Sync` |
| `PhantomData<*const T>` | - | covariant | - | - |
| `PhantomData<*mut T>` | - | invariant | - | - |
| `PhantomData<fn(T)>` | - | contravariant | `Send` | `Sync` |
| `PhantomData<fn() -> T>` | - | covariant | `Send` | `Sync` |
| `PhantomData<fn(T) -> T>` | - | invariant | `Send` | `Sync` |
| `PhantomData<Cell<&'a ()>>` | invariant | - | `Send` | - |
| Phantom type | variance of `'a` | variance of `T` | `Send`/`Sync`<br/>(or lack thereof) | dangling `'a` or `T` in drop glue<br/>(_e.g._, `#[may_dangle] Drop`) |
|-----------------------------|:----------------:|:-----------------:|:-----------------------------------------:|:------------------------------------------------:|
| `PhantomData<T>` | - | **cov**ariant | inherited | disallowed ("owns `T`") |
| `PhantomData<&'a T>` | **cov**ariant | **cov**ariant | `Send + Sync`<br/>requires<br/>`T : Sync` | allowed |
| `PhantomData<&'a mut T>` | **cov**ariant | **inv**ariant | inherited | allowed |
| `PhantomData<*const T>` | - | **cov**ariant | `!Send + !Sync` | allowed |
| `PhantomData<*mut T>` | - | **inv**ariant | `!Send + !Sync` | allowed |
| `PhantomData<fn(T)>` | - | **contra**variant | `Send + Sync` | allowed |
| `PhantomData<fn() -> T>` | - | **cov**ariant | `Send + Sync` | allowed |
| `PhantomData<fn(T) -> T>` | - | **inv**ariant | `Send + Sync` | allowed |
| `PhantomData<Cell<&'a ()>>` | **inv**ariant | - | `Send + !Sync` | allowed |

- 注意: opt-out Unpin 自动特性需要专用的 [`PhantomPinned`] 类型。

[`PhantomPinned`]: https://doc.rust-lang.org/std/marker/struct.PhantomPinned.html
20 changes: 9 additions & 11 deletions src/vec/vec-drain.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl<T> IntoIterator for Vec<T> {
mem::forget(self);
IntoIter {
iter: iter,
iter,
_buf: buf,
}
}
Expand Down Expand Up @@ -131,18 +131,16 @@ impl<'a, T> Drop for Drain<'a, T> {
impl<T> Vec<T> {
pub fn drain(&mut self) -> Drain<T> {
unsafe {
let iter = RawValIter::new(&self);
let iter = unsafe { RawValIter::new(&self) };
// 这里事关 mem::forget 的安全。
// 如果 Drain 被 forget,我们就会泄露整个 Vec 的内存,
// 既然我们始终要做这一步,为何不在这里完成呢?
self.len = 0;
// 这里事关 mem::forget 的安全。
// 如果 Drain 被 forget,我们就会泄露整个 Vec 的内存,
// 既然我们始终要做这一步,为何不在这里完成呢?
self.len = 0;
Drain {
iter: iter,
vec: PhantomData,
}
Drain {
iter: iter,
vec: PhantomData,
}
}
}
Expand Down
44 changes: 23 additions & 21 deletions src/vec/vec-final.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl<T> Vec<T> {

pub fn insert(&mut self, index: usize, elem: T) {
assert!(index <= self.len, "index out of bounds");
if self.cap() == self.len {
if self.len == self.cap() {
self.buf.grow();
}

Expand All @@ -139,14 +139,17 @@ impl<T> Vec<T> {
self.len - index,
);
ptr::write(self.ptr().add(index), elem);
self.len += 1;
}

self.len += 1;
}

pub fn remove(&mut self, index: usize) -> T {
assert!(index < self.len, "index out of bounds");

self.len -= 1;

unsafe {
self.len -= 1;
let result = ptr::read(self.ptr().add(index));
ptr::copy(
self.ptr().add(index + 1),
Expand All @@ -158,18 +161,16 @@ impl<T> Vec<T> {
}

pub fn drain(&mut self) -> Drain<T> {
unsafe {
let iter = RawValIter::new(&self);
let iter = unsafe { RawValIter::new(&self) };

// 这里事关 mem::forget 的安全。
// 如果 Drain 被 forget,我们就会泄露整个 Vec 的内存
// 既然我们始终要做这一步,为何不在这里完成呢?
self.len = 0;
// 这里事关 mem::forget 的安全。
// 如果 Drain 被 forget,我们就会泄露整个 Vec 的内存
// 既然我们始终要做这一步,为何不在这里完成呢?
self.len = 0;

Drain {
iter: iter,
vec: PhantomData,
}
Drain {
iter: iter,
vec: PhantomData,
}
}
}
Expand Down Expand Up @@ -198,14 +199,15 @@ impl<T> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
unsafe {
let iter = RawValIter::new(&self);
let buf = ptr::read(&self.buf);
mem::forget(self);
IntoIter {
iter: iter,
_buf: buf,
}
let (iter, buf) = unsafe {
(RawValIter::new(&self), ptr::read(&self.buf))
};

mem::forget(self);

IntoIter {
iter: iter,
_buf: buf,
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/vec/vec-insert-remove.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub fn insert(&mut self, index: usize, elem: T) {
// 注意:`<=` 是因为我们可以把值插入到任何索引范围 ([0,length-1]) 内的位置之后
// 这种情况等同于 push
assert!(index <= self.len, "index out of bounds");
if self.cap == self.len { self.grow(); }
if self.len == self.cap { self.grow(); }
unsafe {
// ptr::copy(src, dest, len) 的含义: "从 src 复制连续的 len 个元素到 dst "
Expand All @@ -22,8 +22,9 @@ pub fn insert(&mut self, index: usize, elem: T) {
self.len - index,
);
ptr::write(self.ptr.as_ptr().add(index), elem);
self.len += 1;
}
self.len += 1;
}
```

Expand Down
22 changes: 10 additions & 12 deletions src/vec/vec-into-iter.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,16 @@ impl<T> IntoIterator for Vec<T> {
let cap = vec.cap;
let len = vec.len;
unsafe {
IntoIter {
buf: ptr,
cap: cap,
start: ptr.as_ptr(),
end: if cap == 0 {
// 不能通过这个指针获取偏移,因为没有分配内存
ptr.as_ptr()
} else {
ptr.as_ptr().add(len)
},
}
IntoIter {
buf: ptr,
cap,
start: ptr.as_ptr(),
end: if cap == 0 {
// 不能通过这个指针获取偏移,因为没有分配内存
ptr.as_ptr()
} else {
unsafe { ptr.as_ptr().add(len) }
},
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/vec/vec-layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ pub struct Vec<T> {

```rust
use std::ptr::NonNull;
use std::marker::PhantomData;

pub struct Vec<T> {
ptr: NonNull<T>,
Expand Down
32 changes: 15 additions & 17 deletions src/vec/vec-raw.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,23 +130,21 @@ impl<T> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
unsafe {
// 需要使用 ptr::read 非安全地把 buf 移出,因为它没有实现 Copy,
// 而且 Vec 实现了 Drop Trait (因此我们不能销毁它)
let buf = ptr::read(&self.buf);
let len = self.len;
mem::forget(self);
IntoIter {
start: buf.ptr.as_ptr(),
end: if buf.cap == 0 {
// 不能通过这个指针获取偏移,除非已经分配了内存
buf.ptr.as_ptr()
} else {
buf.ptr.as_ptr().add(len)
},
_buf: buf,
}
// 需要使用 ptr::read 非安全地把 buf 移出,因为它没有实现 Copy,
// 而且 Vec 实现了 Drop Trait (因此我们不能销毁它)
let buf = unsafe { ptr::read(&self.buf) };
let len = self.len;
mem::forget(self);
IntoIter {
start: buf.ptr.as_ptr(),
end: if buf.cap == 0 {
// 不能通过这个指针获取偏移,除非已经分配了内存
buf.ptr.as_ptr()
} else {
unsafe { buf.ptr.as_ptr().add(len) }
},
_buf: buf,
}
}
}
Expand Down

0 comments on commit a0607a9

Please sign in to comment.