假设存在以下代码

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人起:

覆盖类型:显示为另一种类型的参数的类型.例如,T未覆盖,但Vec<T>中的T已覆盖.这只与类型参数相关.

重要的是要注意,类型T does not equal是元组类型(T,).(T,)可以被认为等同于标准库箱std中定义的假设的通用新类型/元组 struct struct Tuple1<T>(T).用这个比喻,impl<T: Any> TryFrom<Value> for (T,)相当于impl<T: Any> TryFrom<Value> for std::Tuple1<T>.

注意,覆盖类型(在本例中为单元素元组类型,或在我们的类比中为Tuple1)need not be defined locally在相同的 crate 中.简单地说,考虑一下impl<T> ForeignTrait<LocalType> for ForeignType<T>:

  1. 覆盖类型ForeignType已经被定义.所以:
  2. 唯一可以实现ForeignTrait<LocalType>的方法是 ForeignType<T>在当前 crate 之外是通过泛型 impl <S, T> ForeignTrait<S> for ForeignType<T>(其中S包括 LocalType).
  3. 由于这些规则,覆盖ForeignTrait<LocalType>impl <S, T> ForeignTrait<S> for ForeignType<T>只能在申报ForeignType的 crate 中使用.

因此,ForeignTrait<LocalType>的冲突实现不可能存在于a)本地 crate 和b)声明ForeignType的 crate 之外的ForeignType<T>,因此impl是允许的.更详细的RFC discusses this.

Rust相关问答推荐

即使参数和结果具有相同类型,fn的TypId也会不同

如何在不安全的代码中初始化枚举 struct

空字符串转换为Box字符串时是否分配?<>

如何使用Match比较 struct 中的值

在特征中使用Async时,如何解决不透明类型`impl Future<;out=self>;`不满足其关联的类型边界和警告?

什么时候铁 rust FFI边界上的panic 是未定义的行为?

我如何制作一个变异迭代器来锁定内部数据直到删除?

无法实现整型类型的泛型FN

如何使用Actix Web for Rust高效地为大文件服务

习语选项<;T>;到选项<;U>;当T->;U用From定义

当在lambda中通过引用传递时,为什么会出现终身/类型不匹配错误?

没有明确地说return会产生错误:match arms have incompatible types

如何在 Rust 中将 Vec> 转换为 Vec>?

在异步 Rust 中,Future 如何确保它只调用最近的 Waker?

为什么传递 option.as_ref 的行为不同于使用匹配块并将内部映射到 ref 自己?

是否有适当的方法在参考 1D 中转换 2D 数组

如何将 while 循环内的用户输入添加到 Rust 中的向量?

list 中没有指定目标 - 必须存在 src/lib.rs、src/main.rs、[lib] 部分或 [[bin]] 部分

在同一向量 Rust 中用另一个字符串扩展一个字符串

返回引用的返回函数