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

Type errors with deriving on structures/enums with internal references #15689

Closed
netvl opened this issue Jul 15, 2014 · 11 comments
Closed

Type errors with deriving on structures/enums with internal references #15689

netvl opened this issue Jul 15, 2014 · 11 comments

Comments

@netvl
Copy link
Contributor

netvl commented Jul 15, 2014

This code:

#[deriving(PartialEq)]
enum Test<'a> {
    Slice(&'a int)
}

fn main() {}

fails to compile with the following error:

main2.rs:3:11: 3:18 error: mismatched types: expected `&int` but found `&&'a int` (expected int but found &-ptr)
main2.rs:3     Slice(&'a int)
                     ^~~~~~~
note: in expansion of #[deriving]
main2.rs:1:1: 1:23 note: expansion site
main2.rs:3:11: 3:18 error: mismatched types: expected `&int` but found `&&'a int` (expected int but found &-ptr)
main2.rs:3     Slice(&'a int)
                     ^~~~~~~
note: in expansion of #[deriving]
main2.rs:1:1: 1:23 note: expansion site
error: aborting due to 2 previous errors

Basically I understand the reason for this error, According to rustc --pretty expanded output:

    #[inline]
    fn eq(&self, __arg_0: &Test<'a>) -> ::bool {
        match (&*self, &*__arg_0) {
            (&Slice(ref __self_0), &Slice(ref __arg_1_0)) =>
            true && (*__self_0).eq(&(*__arg_1_0))
        }
    }

here (*__self_0).eq(...) resolves to correct method call due to auto[de]ref on method target, but its argument is still of &&'a int type, which leads to the type error.

I can see why this can be the intended behavior, but I'd argue that this is counterintuitive and very inconvenient: for example, I have a large enum with a lot of references inside its variants, and I'd like to make it comparable with itself, but autoderiving won't work due to this behavior.

@netvl
Copy link
Contributor Author

netvl commented Jul 15, 2014

Same thing with Clone, BTW, which is even more inconvenient, especially provided that references are copyable:

#[deriving(Clone)]
enum Test<'a> {
    Slice(&'a int)
}

fn main() {}
main.rs:3:11: 3:18 error: mismatched types: expected `&int` but found `int` (expected &-ptr but found int)
main.rs:3     Slice(&'a int)
                    ^~~~~~~
note: in expansion of #[deriving]
main.rs:1:1: 1:19 note: expansion site
error: aborting due to previous error

@pnkfelix
Copy link
Member

cc me

@pnkfelix
Copy link
Member

@netvl just checking: Is this an injection from PR #15503 ?

@netvl
Copy link
Contributor Author

netvl commented Jul 16, 2014

@pnkfelix, I did use the most recent nightly, so that PR is probably is present in it, but it happens not only with PartialEq, so I don't know how they really related.

@sfackler
Copy link
Member

@pnkfelix I believe this has been a problem for a while. I don't think it's related to the recent PartialOrd work.

@huonw
Copy link
Member

huonw commented Jul 16, 2014

This has been a problem for a while, and (as @netvl correctly worked out) is caused by autoderef going through the reference. It will be properly fixable with UFCS, since deriving will be able to expand to something like <&'a int for PartialEq>::eq(__self_0, __arg_1_0) and thus avoid auto-deref entirely.

#7621 is similar.

@alexcrichton
Copy link
Member

We can likely get a janky version of ufcs today with something like:

#[automatically_derived]
impl Eq for Foo {
    fn eq(&self, other: &Foo) -> bool {
        fn eq<T: Eq>(t1: &T, t2: &T) -> bool { t1.eq(t2) }
        eq(&self.field1, &other.field1) && ...
    }
}

That should also work for clone and friends (it's how libcore used to do some of its tests)

@alexcrichton
Copy link
Member

"poor man's UFCS"

@huonw huonw changed the title PartialEq deriving for structures/enums with internal references Type errors with deriving on structures/enums with internal references Oct 28, 2014
japaric pushed a commit to japaric/rust that referenced this issue Nov 3, 2014
@alexcrichton
Copy link
Member

Fixed by #18578

@alexcrichton
Copy link
Member

Hm sorry, half-fixed, but the next parts are coming soon in #18467!

japaric pushed a commit to japaric/rust that referenced this issue Nov 6, 2014
@japaric
Copy link
Member

japaric commented Nov 6, 2014

Actually this is 2/3 fixed, #[deriving(PartialOrd)] doesn't work yet. :/

#[deriving(PartialEq, PartialOrd)]
struct Foo(&'static int);
//~^ error: mismatched types: expected `&int`, found `&&'static int` (expected int, found &-ptr)

The problem is the expansion of the partial_cmp method:

fn partial_cmp(&self, __arg_0: &Foo) ->
     ::std::option::Option<::std::cmp::Ordering> {
        match *__arg_0 {
            Foo(ref __self_1_0) =>
            match *self {
                Foo(ref __self_0_0) => {
                    let __test = (*__self_0_0).partial_cmp(&(*__self_1_0));
                    if __test == ::std::option::Some(::std::cmp::Equal) {
                        ::std::option::Some(::std::cmp::Equal)
                    } else { __test }
                }
            },
        }
    }

(*__self_0_0).partial_cmp(&(*__self_1_0)) needs to be changed to its UCFS version: PartialOrd::partial_cmp(&(*__self_0_0), &(*__self_1_0))

I'll send a patch later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants