When should I not implement a trait for references to implementors of that trait?

谁说胖子不能爱 提交于 2019-11-26 06:46:57

问题


If I have a trait, and a function that accepts a generic type constrained to that type, everything works fine. If I try to pass in a reference to that type, I get a compilation error.

trait Trait {
    fn hello(&self) -> u32;
}

struct Struct(u32);

impl Trait for Struct {
    fn hello(&self) -> u32 {
        self.0
    }
}

fn runner<T: Trait>(t: T) {
    println!(\"{}\", t.hello())
}

fn main() {
    let s = Struct(42);

    // Works
    runner(s);

    // Doesn\'t work
    runner(&s);
}
error[E0277]: the trait bound `&Struct: Trait` is not satisfied
  --> src/main.rs:24:5
   |
24 |     runner(&s);
   |     ^^^^^^ the trait `Trait` is not implemented for `&Struct`
   |
   = help: the following implementations were found:
             <Struct as Trait>
note: required by `runner`
  --> src/main.rs:13:1
   |
13 | fn runner<T: Trait>(t: T) {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^

I can fix the issue by implementing the trait for any reference to a type that implements the trait:

impl<\'a, T> Trait for &\'a T
where
    T: Trait,
{
    fn hello(&self) -> u32 {
        (*self).hello()
    }
}

The piece of information that I\'m missing is when shouldn\'t I implement this? Asked another way, why doesn\'t the compiler automatically implement this for me? Since it currently doesn\'t, I assume there must be cases where having this implementation would be disadvantageous.


回答1:


The particular trait you are writing here only takes self by reference, and that is the only reason it is possible to write the additional implementation you did.

For this reason, taking the parameter to runner() by value is probably undesirable; you should instead be taking it by reference. This guideline can apply generally: if it is possible to implement the trait for a reference then rather than wondering “should I implement it?” you should wonder “why would I implement it?” for the only cases where you would use it should probably be altered to take the object by reference in the first place.




回答2:


when shouldn't I implement this? Asked another way, why doesn't the compiler automatically implement this for me? Since it currently doesn't, I assume there must be cases where having this implementation would be disadvantageous.

As an example, the Default trait immediately came to mind.

pub trait Default {
    fn default() -> Self;
}

I could implement it for T, but there is no way to automatically implement it for &T.



来源:https://stackoverflow.com/questions/28799372/when-should-i-not-implement-a-trait-for-references-to-implementors-of-that-trait

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!