【问题标题】:What exactly is the requirement for "covering" a type & why does a single element tuple satisfy it?“覆盖”类型的要求到底是什么?为什么单个元素元组满足它?
【发布时间】:2023-01-11 09:03:41
【问题描述】:

假设存在以下代码

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)

【问题讨论】:

  • 您是否已阅读此问题中接受的答案:stackoverflow.com/a/63131661/4909009
  • @Kendas 我有,除了它仍然没有向我解释 (T,) 如何解决这个问题,它没有在我的板条箱中定义,因为它是原始的。

标签: rust compiler-errors trait-objects


【解决方案1】:

来自RFC 2451

覆盖类型:作为另一个类型的参数出现的类型。例如,T被覆盖,但Vec&lt;T&gt;中的T被覆盖。这仅与类型参数相关。

重要的是要注意类型T不相等元组类型(T,)(T,) 可以被认为等同于标准库 crate std 中定义的假设通用新类型/元组结构 struct Tuple1&lt;T&gt;(T)。以此类推,impl&lt;T: Any&gt; TryFrom&lt;Value&gt; for (T,) 等同于impl&lt;T: Any&gt; TryFrom&lt;Value&gt; for std::Tuple1&lt;T&gt;

请注意覆盖类型(在本例中为单元素元组类型,或者在我们的类比中Tuple1不需要在本地定义在同一个箱子里。简单来说,考虑一个impl&lt;T&gt; ForeignTrait&lt;LocalType&gt; for ForeignType&lt;T&gt;

  1. 已经定义覆盖类型ForeignType。所以:
  2. ForeignTrait&lt;LocalType&gt;的唯一实现方式 ForeignType&lt;T&gt; 当前板条箱之外是通过一个通用的 impl &lt;S, T&gt; ForeignTrait&lt;S&gt; for ForeignType&lt;T&gt;(其中S涵盖 LocalType)。
  3. 由于这些规则,覆盖ForeignTrait&lt;LocalType&gt;impl &lt;S, T&gt; ForeignTrait&lt;S&gt; for ForeignType&lt;T&gt; 只能在声明ForeignType 的箱子中使用。

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

【讨论】:

    猜你喜欢
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-05
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多