关于P210-P211中对协变, 逆变关系的描述
在参考了黑魔法书(nomicon)中subtyping小节的描述:
Some important variances (which we will explain in detail below): &'a T is covariant(协变) over 'a and T (as is *const T by metaphor) &'a mut T is covariant(协变) over 'a but invariant(不变) over T fn(T) -> U is contravariant(逆变) over T, but covariant(协变) over U Box, Vec, and all other collections are covariant(协变) over the types of their contents UnsafeCell<T>, Cell<T>, RefCell<T>, Mutex<T> and all other interior mutability types are invariant(不变) over T (as is *mut T by metaphor)
发现P210-P211中对协变, 逆变关系的描述有点小问题:
fn test_ret<'a>(f: fn() -> &'a str) {
f();
}
fn main(){
fn s() -> &'static str { return ""; }
test_ret(s);
}
(P211) 上面这段代码可以编译通过. 这意味着fn() -> &'static str类型可以安全地转换为fn() -> &'a str. 那我们可以说, 类型fn(T)->U对于参数U具备逆变关系
我们知道, 书中在P210描述:
把一个生命周期更长的引用&'static str, 复制被了一个生命周期更短的引用 &'a str, 这是没有问题的.
这个描述在前文贴出的nomicon一书中得到了确认:
We have already covered why &'a T should be covariant over 'a when introducing subtyping: it's desirable to be able to pass longer-lived things where shorter-lived things are needed.
黑魔法书中表示, 因为生命周期的子类型关系是'long: 'short, 而&'long str转换成&'short str也是没有问题的, 故&'a T对'a是协变(covariant)的. 如果用符号描述, 那应该是:
'long: 'short => &'long str: &'short str
也就是: &'static str : &'a str. 这里借用rust语言中的约束符号(:)来表达左边是右边的子类型. 那么在函数返回值上:
&'static str : &'a str => (fn s() -> &'static str): (fn s() -> &'a str)
理应是协变, 而在函数参数位上:
&'static str : &'a str => fn s(&'a str) : fn s(&'static str)
理应是逆变.
嗯,说得对。这里“逆变”应该改为协变。参数位置上才是逆变。
这个不是笔误或者排版问题。是写的时候脑袋糊了。谢谢!