Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No error for two traits implementing the same method

Tags:

rust

mio

According to the docs, Rust should complain if I try to call a method provided by two different traits like this:

trait Foo {
    fn f(&self);
}

trait Bar {
    fn f(&self);
}

struct Baz;

impl Foo for Baz {
    fn f(&self) { println!("Baz’s impl of Foo"); }
}

impl Bar for Baz {
    fn f(&self) { println!("Baz’s impl of Bar"); }
}

fn main(){
    let b = Baz;
    b.f();
}

Running this results in the expected error: multiple applicable methods in scope error.

However I get no error for this:

extern crate mio;
use mio::buf::RingBuf;
use mio::buf::Buf;
use std::io::Read;

fn main() {
    let buf = RingBuf::new(10);
    let bytes = buf.bytes();
    println!("{:?}", bytes);
}

mio::buf::RingBuf implements both Buf and Read. Both traits provide a bytes method.

I would expect Rust to complain with the same error as above. Instead it silently chooses the "wrong" implementation and later println complains about the wrong type.

Any idea why I don't get an error here?

If I remove use std::io::Read; everything works fine. But with that trait in scope suddenly the implementation of Read is used and bytes has the "wrong" type.

(I am using Rust 1.0.0)

like image 676
michas Avatar asked Jun 07 '15 21:06

michas


1 Answers

@bluss found the problem:

struct Type;

trait A {
    fn foo(&self) -> bool { false }
}

trait B : Sized {
    fn foo(self) -> bool { true }
}

impl A for Type { }
impl B for Type { }

fn main() {
    println!("{}", Type.foo());   // This will call B::foo -- it will prefer `self`.
}

If both types use a slightly different self type, Rust treats them as different and calling the method simply prefers one of them.

This is probably a bug in Rust. For details have a look at the corresponding Rust issue.

like image 104
michas Avatar answered Oct 16 '22 22:10

michas