Skip to content

Autoderef does not find methods on traits in scope #13264

@jdm

Description

@jdm
Contributor

Testcase: https://gist.github.com/jdm/9936609

Note how AddChild is resolved, since it's defined in an impl for JSRef itself, whereas RemoveChild is not resolved since it's a trait method.

RUST_LOG=rustc::middle::typeck::check::method output: https://gist.github.com/jdm/9936635

Activity

alexcrichton

alexcrichton commented on Apr 2, 2014

@alexcrichton
Member

Compiling your example, I get:

<anon>:61:5: 61:23 error: this function takes 1 parameter but 0 parameters were supplied
<anon>:61     root.RemoveChild();
              ^~~~~~~~~~~~~~~~~~
<anon>:62:5: 62:24 error: this function takes 1 parameter but 0 parameters were supplied
<anon>:62     jsref.RemoveChild();
              ^~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors

Which I believe is working as intended. Currently inherent methods shadow trait methods.

jdm

jdm commented on Apr 2, 2014

@jdm
ContributorAuthor

@alexcrichton If I comment out the Deref impl, it compiles without issue.

alexcrichton

alexcrichton commented on Apr 2, 2014

@alexcrichton
Member

Ah, don't mind me, I think I see what's going on.

jdm

jdm commented on Apr 2, 2014

@jdm
ContributorAuthor
[11:44:27] <nmatsakis> jdm: the reason you're seeing an error there is because we always favor inherent methods over trait methods
[11:44:31] <nmatsakis> jdm: currently, at least.
nikomatsakis

nikomatsakis commented on Apr 2, 2014

@nikomatsakis
Contributor

The reason for this rule is to permit impls like impl Trait for ~Trait { ... }, since otherwise they result in infinite recursion cycles.

ghost

ghost commented on Nov 11, 2014

@ghost

Updated test case:

struct Root {
    jsref: JSRef
}

impl Deref<JSRef> for Root {
    fn deref<'a>(&'a self) -> &'a JSRef {
        &self.jsref
    }
}

struct JSRef {
    node: *const Node
}

impl Deref<Node> for JSRef {
    fn deref<'a>(&'a self) -> &'a Node {
        self.get()
    }
}

trait INode {
    fn RemoveChild(&self);
}

impl INode for JSRef {
    fn RemoveChild(&self) {
        self.get().RemoveChild(0)
    }
}

impl JSRef {
    fn AddChild(&self) {
        self.get().AddChild(0);
    }

    fn get<'a>(&'a self) -> &'a Node {
        unsafe {
            &*self.node
        }
    }
}

struct Node;

impl Node {
    fn RemoveChild(&self, _a: uint) {
    }

    fn AddChild(&self, _a: uint) {
    }
}

fn main() {
    let n = Node;
    let jsref = JSRef { node: &n };
    let root = Root { jsref: jsref };

    root.AddChild();
    jsref.AddChild();

    root.RemoveChild();
    jsref.RemoveChild();
}

E-needstest.

ghost added
E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
on Nov 11, 2014
nikomatsakis

nikomatsakis commented on Nov 11, 2014

@nikomatsakis
Contributor

For more context: we changed the priorities so that inherent methods only override extension methods at a given autoderef level, which I think is close enough to the behavior that @jdm wanted for this test case.

added 3 commits that reference this issue on Dec 12, 2014
20cbbff
c59b9b7
added a commit that references this issue on Oct 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @jdm@alexcrichton@nikomatsakis

      Issue actions

        Autoderef does not find methods on traits in scope · Issue #13264 · rust-lang/rust