为什么Rust禁止对现有类型进行实现?

4

这个是怎么...

impl String {
    fn foo(&self) {
        //...
    }
}

还有其他不同的方式吗?

fn foo(s: &String) {
    //...
}

然而,如果您在您的crate中定义了一个trait,就有可能扩展类型实现。为什么呢?


6
相关RFC:https://github.com/rust-lang/rfcs/issues/493。更具体地,您可能希望跳转到讨论的这一部分:https://github.com/rust-lang/rfcs/issues/493#issuecomment-266307203 - asteriskTheServer
6
@asteriskTheServer:这听起来像是一个不错的评论回答。为什么不试着将其转化为一个合适的回答,使用该评论作为来源呢? - Matthieu M.
2
这里似乎存在一个可见性问题;您期望如何控制String::foo的可见性?Trait支持添加新的方法:trait Foo { fn foo(&self); } impl Foo for String { ... }。在这里,可以通过导入Trait来控制String::foo的可见性,并且可以使用完整的Trait名称消除实现foo的不同Trait之间的歧义。 - user4815162342
@user4815162342 但是为什么不允许私有实现呢? - Sogomn
我刚刚重新阅读了你在@asteriskTheServer发布的RFC,现在我想我明白了。公共实现将向其他板条箱公开更改,而本地实现将覆盖未来的补丁。 - Sogomn
1个回答

2
以下来源列举了几个不同的理由,解释为什么无法在自己的 crate 中实现现有的类型。
  • Local impl can be broken by future implementations. For example, consider "you've locally defined Add on Vec<T> as a concat operator, ... , and then ... after years of debate ... some mathy operation [is] to be performed instead. If you delete your impl and upgrade, your code will be ... broken2."

  • The readability of the code will also be affected by this change, that is, it could make the "value of that reading far more transient3."

  • There is also a security concern. Consider the following scenario that would be technically possible if this were allowed, that is, "an attacker [could] find a change in an impl in [some] library, a call site in an application they wish to backdoor, and send a "refactoring" pull request that "accidentally" replaces the new impl with the old impl so as to create a vulnerability, but their pull can reference the old code from the library. And they can embed the hostile impl into a macro in yet another create4."

  • Assuming the case that the local impl would be the preferred implementation if local impls were allowed. This would "would violate the coherence property [that is currently being maintained]5." This point can be further clarified through what is called the 'HashTable' problem5.

    mod foo {
        impl Hash for i32 { ... }
    
        fn f(mut table: HashMap<i32, &'static str>) {
            table.insert(0, "hello");
            ::bar::f(&table);
        }
    }
    
    mod bar {
        impl Hash for i32 { ... }
    
        fn f(table: &HashMap<i32, &'static str>) {
            assert_eq!(table.get(0), Some("hello"));
        }
    }
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接