为什么忽略了在特征实现上发送的特质边界?



为什么自动特性Send特征实现的特质边界被忽略了? (游乐场(1((

trait IsSend {
fn is_send(&self);
}
impl<T: Send> IsSend for T {
fn is_send(&self) {}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let i = std::rc::Rc::new(43);
i.is_send(); // (!!) no compiler error although Rc<...> is not Send
Ok(())
}

例如,使用绑定为自定义特征 (X( 绑定的特质,它可以工作: (游乐场(2((

trait X {}
trait IsSend {
fn is_send(&self);
}
impl<T: X> IsSend for T {
fn is_send(&self) {}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let i = std::rc::Rc::new(43);
i.is_send(); // (ok) compiler error as Rc<...> does not implement X
Ok(())
}

更令人困惑的是,使用绑定在函数上的特征,它可以按预期工作:(游乐场(3((

fn is_send<T: Send>(_s: &T) {}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let i = std::rc::Rc::new(43);
is_send(&i); // (ok) compiler as Rc<...> is not Send
Ok(())
}

看起来自动性状Send(或一般的自动性状(被特殊对待。但是,我没有找到任何有关此的文档。这是一个错误还是只是我缺乏理解:-(?

看看这个稍微修改过的游乐场版本

use std::any::TypeId;
trait IsSend {
fn is_send(&self);    
}
impl<T: Send + 'static> IsSend for T {
fn is_send(&self){
println!("TypeId of T: {:?}", TypeId::of::<T>());
}
}
fn main() -> Result<(),Box<dyn std::error::Error>> {
println!("TypeId of i32: {:?}", TypeId::of::<i32>());
println!("TypeId of Rc<i32>: {:?}", TypeId::of::<std::rc::Rc<i32>>());
let i = std::rc::Rc::new(43);
i.is_send(); // (!!) no compiler error although Rc is not Send
Ok(())
}

我们得到的结果是:

TypeId of i32: TypeId { t: 13431306602944299956 }
TypeId of Rc<i32>: TypeId { t: 1918842018359854094 }
TypeId of T: TypeId { t: 13431306602944299956 }

我改变了:

  • 添加了一些println!调用,以便我们可以看到类型的 TypeId
  • 由于TypeId约束,添加了要求T: 'static。这不应该影响我们的答案,因为Rc<i32>i32都是'static.

可以看出,T解析为i32而不是Rc<i32>。也就是说,is_send是用T = i32而不是T = Rc<i32>来调用的。

这是因为Rc<T>实现了Deref<Target = T>。当你调用i.is_send()时,它实际上等价于(*i).is_send(),而*i是一个i32,这是一个Send。当您使用点运算符对值调用方法时,编译器会尝试执行取消引用,直到满足类型边界。

为了说明这一点,让我们尝试将Rc更改为Arc,其中Arc实现Send。您可以看到T现在具有与Arc<i32>相同的TypeId,而不是i32。这是因为Arc已经满足T: Send绑定,不需要进一步取消引用。

use std::any::TypeId;
use std::sync::Arc;
trait IsSend {
fn is_send(&self);    
}
impl<T: Send + 'static> IsSend for T {
fn is_send(&self){
println!("TypeId of T: {:?}", TypeId::of::<T>());
}
}
fn main() -> Result<(),Box<dyn std::error::Error>> {
println!("TypeId of i32: {:?}", TypeId::of::<i32>());
println!("TypeId of Arc<i32>: {:?}", TypeId::of::<Arc<i32>>());
let i = Arc::new(43);
i.is_send(); // (!!) no compiler error although Rc is not Send
Ok(())
}
TypeId of i32: TypeId { t: 13431306602944299956 }
TypeId of Arc<i32>: TypeId { t: 3504454246784010795 }
TypeId of T: TypeId { t: 3504454246784010795 }

相关内容

  • 没有找到相关文章

最新更新