Skip to content

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

New issue

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

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

Already on GitHub? # to your account

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.

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

No branches or pull requests

6 participants