[英]Why are trait bounds for Send on trait implementations ignored?
為什么忽略自動特征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!
調用,以便我們可以看到類型的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 }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.