use*_*169 8 generics dereference rust
为什么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)的特征可以工作:(Playground(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(())
}
更令人困惑的是,使用绑定在函数上的特征按预期工作:(Playground(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!调用,以便我们可以看到类型的 TypeIdT: 'static由于限制,添加了一个要求TypeId。这不应该影响我们的答案,因为Rc<i32>和i32都是'static。可以看出 被T解析为 asi32而不是Rc<i32>。也就是说,is_send被称为 withT = i32而不是T = Rc<i32>。
这是因为Rc<T>实施Deref<Target = T>. 当你调用时i.is_send(),它实际上相当于(*i).is_send(), and *iis an i32,即 a Send。当您使用点运算符对值调用方法时,编译器会尝试执行取消引用,直到满足类型边界。
为了说明这一点,让我们尝试更改Rc为Arc,其中Arcimplements Send。您可以看到T现在具有与 相同的 TypeId,而Arc<i32>不是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 }
| 归档时间: | 
 | 
| 查看次数: | 68 次 | 
| 最近记录: |