【问题标题】:Why is it possible to implement a trait for both `T: Display` and `str`?为什么可以同时为 `T: Display` 和 `str` 实现 trait?
【发布时间】:2019-03-04 06:24:49
【问题描述】:

stable Rust yet 中没有 specialization,所以这不起作用:

trait X {}

impl<T> X for T {}
impl X for u32 {}  // conflicting implementation

这并不奇怪:X 是为任何类型 T 实现的,我们不能为 u32 再次实现它。

令人惊讶的是,以下 sn-p 编译成功:

use std::fmt::Display;

pub trait Show {}

impl<T: Display> Show for T {}

impl Show for str {}

// These impls would cause "conflicting implementation" errors:
// impl<'a> Show for &'a str
// impl Show for String

fn main() {}

我不希望这段代码编译,因为Display is implemented for str,所以泛型impl应该为str实现Show并与特定impl冲突。

为什么impl Show for strimpl&lt;T: Display&gt; Show for T不冲突?

【问题讨论】:

    标签: rust


    【解决方案1】:

    绑定的&lt;T: Display&gt; 隐式假定T 必须是Sized 类型。但是strunsized。因此,这两个 impl 并不相互冲突。

    如果您还需要覆盖像str 这样的无尺寸类型,则需要通过添加T: ?Sized 来放宽尺寸要求:

    impl<T: Display + ?Sized> Show for T {}
    //              ^~~~~~~~
    

    【讨论】:

    • 一见钟情:play.rust-lang.org/…
    • @Boiethios 这正是我偶然发现的原因。实际上有点好,它允许“专门化”字符串切片。
    • @Boiethios 这不是专业化。 str 不满足另一个 impl 中 T 的要求,因此它们不会重叠。你在那儿看到的是Show impl for &amp;str 而不是str
    • 但是,老实说,这感觉有点恶心。 autoref 规则使这变得非常混乱,因为您仅使用大小的类型会获得不同的行为。
    • @PeterHall 我知道!这就是我写的原因:看起来像
    猜你喜欢
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-17
    • 2011-06-14
    相关资源
    最近更新 更多