No error despite of multiple applicable methods in scope

bb35add
Opened by Michael Schnupp at 2022-10-17 19:18:42

Given the following code:

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);
}

buf is of type RingBuf. RingBuf does not provide .bytes(), but it implements both Buf and Read, which both provide a .bytes() implementation.

According to https://doc.rust-lang.org/book/ufcs.html the compiler should complain. But it simply chooses to take the implementation of Read, which return the "wrong" result type.

(Without the "use Read" line rust chooses the implementation of Buf, which return the "correct" type.)

(I am using Rust 1.0.0.)

  1. Edit: Found a good reproduction, I think this explains the situation. I'm still surprised that this is allowed, but the methods in question have different self type -- &self vs self.

    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`.
    }
    

    bluss at 2015-06-07 22:45:15

  2. UFCS is not used here (that would be <RingBuf>::bytes). Method lookup tries autoderefs/autorefs in the order 0 autoderef -> 0 autoderef + autoref -> 1 autoderef -> 1 autoderef + autoref -> .... This is required for e.g. rc.clone() (but, of course, not for <Rc>::clone) to work.

    We might want to make k autoderefs be ambiguous with k autoderefs + autoref, but this is of course a breaking change (an annotatable one, through) and somebody may be relying on it.

    Ariel Ben-Yehuda at 2015-06-08 16:53:07

  3. @michas2 It may be that it's a known "feature" of method look up priorities, yours and my example both use the fact that the methods use self vs. &self and thus the self is preferred.

    It's confusing but perhaps not a bug like I thought!

    As @arielb1 says, using the <Typename>::bytes(...) syntax will produce the ambiguous methods error message.

    bluss at 2015-06-08 17:23:19

  4. triage: I-nominated

    Alex Crichton at 2015-06-08 17:23:50

  5. triage: still an issue.

    Felix S Klock II at 2017-01-03 16:11:58

  6. Triage: still reproduces, not something that I think we're likely to change?

    Steve Klabnik at 2019-12-25 16:15:06

  7. Triage: still reproduces

    Do we still consider this a bug?

    Maayan Hanin at 2022-10-17 19:18:42