在阅读Nomicon的子类型章节之后,我就无法将类型参数的协方差包住。特别是对于Box<T>类型,它被描述为:T is covariant。
但是,如果我编写此代码:
trait A {}
trait B: A {}
struct C;
impl A for C {}
impl B for C {}
fn foo(v: Box<A>) {}
fn main() {
let c = C;
let b: Box<B> = Box::new(c);
foo(b);
}
Run Code Online (Sandbox Code Playgroud)
(游乐场)
trait A {}
trait B: A {}
struct C;
impl A for C {}
impl B for C {}
fn foo(v: Box<A>) {}
fn main() {
let c = C;
let b: Box<B> = Box::new(c);
foo(b);
}
Run Code Online (Sandbox Code Playgroud)
B显然是的“子类型”,A并且Box在其输入上是协变的。我不知道为什么它不起作用或为什么它不执行任何类型的强制转换。Box<T>在唯一的用例是不变式的情况下,为什么他们会认为是协变的?
Nomicon不是完全抛光的文档。目前,该回购协议中最近发行的10个问题中有5个专门根据其标题来处理子类型或差异。Nomicon中的概念可能需要大量的精力,但信息通常存在。
首先,请查看一些初始段落(重点是我的):
Rust中的子类型与其他语言中的子类型有些不同。这使得很难给出简单的例子,这是一个问题,因为子类型,尤其是方差,已经很难正确理解。
为了使事情简单,本节将考虑对Rust语言的一个小扩展,它增加了新的和更简单的子类型关系。在这个简单的系统下建立概念和问题之后,我们将把它与Rust中子类型的实际发生方式联系起来。
然后继续显示一些基于特征的代码。重申一点,这个代码是不生锈的代码了; 特质在Rust中不构成子类型!
稍后,有这句话:
首先,基于引用的生存期进行子类型化是Rust 中子类型化的全部要点。我们拥有子类型化的唯一原因是,我们可以在预期寿命短的地方传递寿命长的东西。
Rust的子类型化概念仅适用于生存期。
这是一个示例子类型和寿命的变化Box。
失败的案例
fn smaller<'a>(v: Box<&'a i32>) {
bigger(v)
}
fn bigger(v: Box<&'static i32>) {}
Run Code Online (Sandbox Code Playgroud)
fn smaller<'a>(v: Box<&'a i32>) {
bigger(v)
}
fn bigger(v: Box<&'static i32>) {}
Run Code Online (Sandbox Code Playgroud)
一个工作案例
fn smaller<'a>(v: Box<&'a i32>) {}
fn bigger(v: Box<&'static i32>) {
smaller(v)
}
Run Code Online (Sandbox Code Playgroud)
这是一个可行的情况:
struct S<'a>(&'a i32);
fn smaller<'a>(_v: &S<'a>, _x: &'a i32) {}
fn bigger(v: &S<'static>) {
let x: i32 = 1;
smaller(v, &x);
}
Run Code Online (Sandbox Code Playgroud)
将所有引用更改为可变引用的相同代码将失败,因为可变引用是不变的:
struct S<'a>(&'a mut i32);
fn smaller<'a>(_v: &mut S<'a>, _x: &'a mut i32) {}
fn bigger(v: &mut S<'static>) {
let mut x: i32 = 1;
smaller(v, &mut x);
}
Run Code Online (Sandbox Code Playgroud)
error[E0308]: mismatched types
--> src/lib.rs:2:12
|
2 | bigger(v)
| ^ lifetime mismatch
|
= note: expected type `std::boxed::Box<&'static i32>`
found type `std::boxed::Box<&'a i32>`
note: the lifetime 'a as defined on the function body at 1:12...
--> src/lib.rs:1:12
|
1 | fn smaller<'a>(v: Box<&'a i32>) {
| ^^
= note: ...does not necessarily outlive the static lifetime
Run Code Online (Sandbox Code Playgroud)
B显然是的“子类型”A
它不是。
Box在输入上是协变的
也就是协方差仅适用于寿命。
我不知道为什么它不起作用或为什么它不执行任何类型的强制转换。
这是通过覆盖为什么不生锈特性的支持对象向上转型?
他们为什么会认为
Box<T>是协变的
因为是这样,对于Rust中适用于差异的事物。
| 归档时间: |
|
| 查看次数: |
185 次 |
| 最近记录: |