Skip to content

Commit

Permalink
修复子类型化和变异性章节的部分翻译 (#38)
Browse files Browse the repository at this point in the history
* fix(subtyping): 修复子类型化和变异性章节的两个小问题

* fix(subtyping): 更正子类型化和变异性章节的部分翻译
  • Loading branch information
any-yi authored Dec 14, 2023
1 parent f045b7e commit 07674e3
Showing 1 changed file with 8 additions and 8 deletions.
16 changes: 8 additions & 8 deletions src/subtyping.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ error[E0308]: mismatched types
`'long` 可能定义了一个比 `'short` 更大的区域,但这仍符合我们的定义。

> 虽然在本章后面,子类型化比这要复杂得多,但这个简单的规则在大多数情况下都适用。除非您编写不安全的代码,否则编译器将为您自动处理所有的特殊情况。
> 虽然在本章后面,子类型化比这要复杂和微妙得多,但这个简单的规则在大多数情况下都适用。除非您编写不安全的代码,否则编译器将为您自动处理所有的特殊情况。
> 但这是 Rustonomicon。我们正在编写不安全的代码,所以我们需要了解这些东西是如何真正工作的,以及我们如何搞乱它。
Expand Down Expand Up @@ -104,19 +104,19 @@ fn main() {
我们第一反应可能是怪 `assign` 的实现,但实际上这里并没有什么错误。一个值想要赋值到一个具有相同类型的 `T` 也不奇怪。

所以,问题在于,我们不能假设 `&mut &'static str` 也可以转换成 `&mut &'b str`
这意味着,即使 `'static``&'b` 的子类型,`&mut &'static str`**不能**`&mut &'b str` 的子类型。
这意味着,即使 `'static``'b` 的子类型,`&mut &'static str`**不能**`&mut &'b str` 的子类型。

**变异性** 是 Rust 引用的一个性质 ,用于定义泛型参数之间的子类型 (也就是包含与被包含) 关系
**变异性** 是 Rust 引用通过它们的泛型参数,来定义引用之间的子类型关系

> 注意:为了方便起见,我们将定义一个泛型类型 `F<T>`,以便我们可以方便地讨论 `T`。希望这在上下文中是清楚的。
类型 `F`*变异性* 与它的泛型参数有关
类型 `F`*变异性* 代表了其输入子类型如何影响其输出子类型

在 Rust 中有三种变异性,假设 `Sub``Super` 的子类型:

* `F`**协变的**,如果 `F<Sub>``F<Super>` 的子类型(子类型属性被传递)(译者注:即生命周期 `Sub` 可以收缩成 `Super`)
* `F`**逆变的**,如果 `F<Super>``F<Sub>` 的子类型(子类型属性被 "反转")(译者注:即生命周期 `Sub` 可以扩大成 `Super`)
* 否则,`F`**不变的** (不存在子类型关系)(译者注:即生命周期不能发生变化)
* `F`**协变的**,如果 `F<Sub>``F<Super>` 的子类型(子类型属性被传递)(译者注:这里被传递的意思是尖括号里面的子类型关系(`Sub <: Super`)被传递到尖括号外(`F<Sub> <: F<Super>`))
* `F`**逆变的**,如果 `F<Super>``F<Sub>` 的子类型(子类型属性被 "反转")(译者注:即尖括号里面的子类型关系(`Sub <: Super`)在尖括号外面被反转(`F<Super> <: F<Sub>`))
* 否则,`F`**不变的** (不存在子类型关系)(译者注:即尖括号里面的子类型关系不会影响尖括号外面的子类型关系)

让我们回想上面的例子,如果 `'a``'b` 的子类型,我们可以将 `&'a T` 视作是 `&'b T` 的子类型,因而`&'a T`对于 `'a` 上是协变的。

Expand Down Expand Up @@ -206,7 +206,7 @@ fn debug<T: std::fmt::Debug>(a: T, b: T) {
}
```

尽管 `a``b` 必须具有相同的类型 `T`,但由于 `&'a T``'a` 上是协变的,我们可以执行子类型化。因此,编译器认为,`'static <: 'b` 的情况下, `&'static str` 可以变为 `&'b str` ,因此 `&'static str` `&'b str` 的子类型。这是正确的,因此编译器愿意继续编译此代码
尽管 `a``b` 必须具有相同的类型 `T`,但由于 `&'a T``'a` 上是协变的,我们可以执行子类型化。因此,编译器认为,当且仅当 `&'static str` `&'b str` 的子类型时(这种关系在 `'static <: 'b` 时成立),`&'static str` 才可以变为 `&'b str`。这是正确的,因此编译器很乐意继续编译这段代码

事实证明,Box(以及 Vec,HashMap 等)协变的原因与生命周期协变的原因相似:只要你尝试将它们放入诸如可变引用之类的东西中,就会继承不变性,从而阻止你做任何坏事。

Expand Down

0 comments on commit 07674e3

Please sign in to comment.