Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Method resolution bug in presence of default trait implementations #23519

Closed
petrochenkov opened this issue Mar 19, 2015 · 1 comment
Closed
Labels
A-resolve Area: Name resolution

Comments

@petrochenkov
Copy link
Contributor

The next program

#![feature(core)]
#![feature(optin_builtin_traits)]

// A trait implemented for non-references
trait NonRef: std::marker::MarkerTrait {}
impl NonRef for .. {}
impl<'a, T> !NonRef for &'a T {}
// impl NonRef for i32 {}
// impl<T> NonRef for S<T> {}

// A trait similar to PartialEq
trait PartialQe<R> {
    fn qe(&self, right: &R);
}

// Blanket impl for qe(Ref, Ref)
impl<'l, 'r, L, R> PartialQe<&'r R> for &'l L where L: PartialQe<R>
{
    fn qe(&self, right: &&'r R) {
        println!("Blanket impl: Ref, Ref");
        PartialQe::qe(*self, *right);
    }
}
// Blanket impl for qe(Ref, NonRef)
impl<'l, L, R: NonRef> PartialQe<R> for &'l L where L: PartialQe<R>
{
    fn qe(&self, right: &R) {
        println!("Blanket impl: Ref, NonRef");
        PartialQe::qe(*self, right);
    }
}

struct S<T>(T);

// Concrete impl for qe(S(a), S(b))
impl<L, R> PartialQe<S<R>> for S<L> where L: PartialQe<R> {
    fn qe(&self, right: &S<R>) {
        println!("Concrete impl for S: NonRef, NonRef");
        PartialQe::qe(&self.0, &right.0);
    }
}
// Concrete impl for qe(i32, i32)
impl PartialQe<i32> for i32 {
    fn qe(&self, _right: &i32) { println!("Concrete impl for i32: NonRef, NonRef") }
}

fn main() {
    let z = 0i32;
    PartialQe::qe(&&S(&z), &S(&z));
}

is supposed to compile and print

Blanket impl: Ref, NonRef
Concrete impl for S: NonRef, NonRef
Blanket impl: Ref, Ref
Concrete impl for i32: NonRef, NonRef

but it doesn't compile with an error

<anon>:42:5: 42:18 error: the trait `NonRef` is not implemented for the type `&i32` [E0277]

If I switch the comments in lines

impl NonRef for .. {}
impl<'a, T> !NonRef for &'a T {}
// impl NonRef for i32 {}
// impl<T> NonRef for S<T> {}

then everything works as expected.

cc @flaper87 @nikomatsakis

@petrochenkov
Copy link
Contributor Author

Closing, this is by design.
If !NonRef is implemented for &T it also becomes implemented for S<&T> or any other type containing &T. It is weird, but it's how OIBIT work, they are just not designed to be used for specialization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-resolve Area: Name resolution
Projects
None yet
Development

No branches or pull requests

2 participants