[英]Apply trait bounds to associated type
假設我有這樣的特征:
trait InternalError {
fn internal(error: String) -> Self;
}
如果我想在函數中使用它,我可以這樣做:
struct MyU16(pub u16);
fn my_try_from<E: InternalError>(value: u32) -> Result<MyU16, E> {
if value < u16::MAX as u32 {
Ok(MyU16(value as u16))
} else {
Err(E::internal("invalid".to_string()))
}
}
這很好用。
現在想象一下,我想使用TryFrom
,而不是使用我自己的函數:
impl<E: InternalError> TryFrom<u32> for MyU16 {
type Error = E;
fn try_from(value: u32) -> Result<Self, Self::Error> {
if value < u16::MAX as u32 {
Ok(MyU16(value as u16))
} else {
Err(E::internal("invalid".to_string()))
}
}
}
然而,這不起作用。 我嘗試了各種不同的方式來表達這一點,但我無法弄清楚如何說“這個 TryFrom impl,在錯誤的情況下,返回一些 impls InternalError 的東西”。
任何有關如何正確執行此操作的建議將不勝感激。 謝謝!
這個 TryFrom impl,在錯誤的情況下,返回一些 impls InternalError
TryFrom
想在編譯時知道返回了什么樣的錯誤。 您似乎想在運行時決定類型。
假設FirstError
和SecondError
都實現了InternalError
。
在這種情況下
impl TryFrom<u32> for MyU16 {
type Error = FirstError;
fn try_from(value: u32) -> Result<Self, FirstError> {
/*...*/
}
}
會編譯,但當然try_from
只能返回FirstError
。
但是,如果您想在運行時在FirstError
和SecondError
之間做出決定。 相關的錯誤類型(不是特征)需要能夠同時包含兩者。
impl TryFrom<u32> for MyU16 {
type Error = Box<dyn InternalError>;
fn try_from(value: u32) -> Result<Self, Box<dyn InternalError>> {
/*...*/
Box::new(FirstError::internal("invalid".to_string()))
}
}
這也暗示了為什么enum
是 Rust 中表示錯誤的慣用方式:通常你在編譯時不知道會出現什么問題。 因此,一個可以列出所有狀態的enum
可以讓用戶清楚地知道可能出現的問題,並且在許多情況下,您可以在沒有額外堆分配的情況下創建錯誤。
它無法編譯的原因是impl
聲明中的類型參數必須出現在實現類型( impl<T> Foo<T>
)或實現的特征( impl<T> MyTrait<T> for Foo
)。 您不能只impl<T> for Foo
並且只在impl
塊中再次提及T
。
正如擴展錯誤所暗示的那樣,有一種解決方法將幻像類型引入實現類型,但您可能不喜歡它使您的代碼看起來如何:
use std::marker::PhantomData;
struct MyU16<T>(pub u16, PhantomData<T>);
impl<E: InternalError> TryFrom<u32> for MyU16<E> {
type Error = E;
fn try_from(value: u32) -> Result<Self, Self::Error> {
if value < u16::MAX as u32 {
Ok(MyU16(value as u16, PhantomData))
} else {
Err(E::internal("invalid".to_string()))
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.