rust - "covering"类型的要求到底是什么?为什么单个元素元组可以满足它?

标签 rust compiler-errors trait-objects

假设存在以下代码

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 the T in Vec<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> :

  1. 覆盖类型ForeignType已经被定义了。所以:
  2. 唯一的办法ForeignTrait<LocalType>可以实现为 ForeignType<T>当前 crate 外部是通过通用的 impl <S, T> ForeignTrait<S> for ForeignType<T> (其中 S 涵盖 LocalType )。
  3. 由于这些规则,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/

相关文章:

rust - 错误 : failed to run custom build command for `onig_sys v61.1.0`

makefile - `make` 没有注意到 Rust 模块中的修改 - 如何更好地将 Rust 集成到构建中?

rust - 你如何使用它自己的 crate 中的宏?

c++ - 从点创建集合时出错

generics - 为什么 `&(?Sized + Trait)`无法转换为 `&dyn Trait`?

rust - 如何制作具有特征的泛型的泛型?

c++ - 时间:2019-01-09标签:std::sort intel compiler error : access violation

c++ - 编译错误 - 数组下标的无效类型 'char[int]'

rust - 如何在 Rust 中定义递归特征?

rust - 错误 E0277 以下书籍示例 dyn Trait,如何将 dyn Trait 推送到向量中?