假设存在以下代码
use core::any::Any;
enum Value {
Any(Box<dyn Any>),
Other, // placeholder, this code is adapted from mine
}
此代码提出了我不太理解的诊断
impl<T: Any> TryFrom<Value> for T {
type Error = &'static str;
fn try_from(val: Value) -> Result<Self, Self::Error> {
if let Value::Any(any) = val {
if let Ok(down) = any.downcast::<T>() {
Ok(*down)
} else {
Err("incorrect type")
}
} else { Err("not an any") }
}
}
fn main() {
let res: Result<usize, &'static str> = Value::Any(Box::new(1usize)).try_into();
dbg!(res);
}
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Value`)
--> src/main.rs:9:6
|
9 | impl<T: Any> TryFrom<Value> for T {
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Value`)
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
我仍然不太明白“必须被另一种类型覆盖”是什么意思,也不明白“当它出现在第一个本地类型之前”是什么意思。
但是,如果我修改 impl 签名以定位包含 T 的单元素元组,则 impl 不会引发错误,并且代码可以正常运行:
impl<T: Any> TryFrom<Value> for (T,) {
type Error = &'static str;
fn try_from(val: Value) -> Result<Self, Self::Error> {
if let Value::Any(any) = val {
if let Ok(down) = any.downcast::<T>() {
Ok((*down,))
} else {
Err("incorrect type")
}
} else { Err("not an any") }
}
}
fn main() {
let res: Result<(usize,), &'static str> = Value::Any(Box::new(1usize)).try_into();
dbg!(res);
}
单元素元组实际上有什么用途?
( Playground Link )
最佳答案
来自RFC 2451 :
Covered Type: A type which appears as a parameter to another type. For example,
T
is uncovered, but theT
inVec<T>
is covered. This is only relevant for type parameters.
需要注意的是,类型T
不等于元组类型 (T,)
。 (T,)
可以被认为等同于假设的通用新类型/元组结构 struct Tuple1<T>(T)
在标准库 crate std
中定义。以此类比,impl<T: Any> TryFrom<Value> for (T,)
相当于 impl<T: Any> TryFrom<Value> for std::Tuple1<T>
.
请注意,覆盖类型(在本例中为单元素元组类型,或在我们的类比中 Tuple1
)不需要在同一个包中本地定义。简而言之,考虑 impl<T> ForeignTrait<LocalType> for ForeignType<T>
:
- 覆盖类型
ForeignType
已经被定义了。所以: - 唯一的办法
ForeignTrait<LocalType>
可以实现为ForeignType<T>
当前 crate 外部是通过通用的impl <S, T> ForeignTrait<S> for ForeignType<T>
(其中S
涵盖LocalType
)。 - 由于这些规则,
impl <S, T> ForeignTrait<S> for ForeignType<T>
涵盖ForeignTrait<LocalType>
只能在声明ForeignType
的箱子中使用.
因此 ForeignTrait<LocalType>
的实现不可能发生冲突存在于ForeignType<T>
在 a) 本地 crate 和 b) 声明 ForeignType
的 crate 之外,所以 impl
被允许。 RFC discusses this更详细。
关于rust - "covering"类型的要求到底是什么?为什么单个元素元组可以满足它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75075748/