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

== fails to match types on associated type with two PartialEq<A / B> bounds #34792

Open
SimonSapin opened this Issue Jul 12, 2016 · 7 comments

Comments

Projects
None yet
8 participants
@SimonSapin
Copy link
Contributor

SimonSapin commented Jul 12, 2016

rustc 1.12.0-nightly (47b3a98 2016-07-10)

pub struct A;
pub struct B;

pub trait Foo {
    type T: PartialEq<A> + PartialEq<B>;
}

pub fn generic<F: Foo>(t: F::T, a: A, b: B) -> bool {
    t == a && t == b
}
error: mismatched types [--explain E0308]
  --> a.rs:12:10
   |>
12 |>     t == a && t == b
   |>          ^ expected struct `B`, found struct `A`
note: expected type `B`
note:    found type `A`

error: aborting due to previous error

Changing the order of bounds in the associated type declaration changes which == causes a spurious "mismatched types" error.

Using UFCS works around the issue:

    PartialEq::<A>::eq(&t, &a) && t == b

The same issue exists with bounds like type T: PartialEq + PartialEq<B> to compare T with itself as well as another type.

@rkruppe

This comment has been minimized.

Copy link
Member

rkruppe commented Jul 13, 2016

cf. #24066

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Jul 16, 2016

Looks like this is caused by using find on the set of bounds from the trait, but that is just find the first one (in the order they are internally stored), this needs to filter and produce a vector of bounds or something similar.

cc @rust-lang/compiler

@rozbb

This comment has been minimized.

Copy link

rozbb commented Jul 18, 2016

Update: using filter and then calling candidates.extend on all matching bounds does not fix this issue.

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Jul 18, 2016

@doomrobo I believe your problem is this logic.
Right now it works fine because the if victim.candidate == other.candidate above would trigger for ObjectCandidate vs ObjectCandidate or ParamCandidate vs ParamCandidate.

However, it's incorrect with your changes as ParamCandidate(bound_a) is dropped in favor of ParamCandidate(bound_b) even if bound_a and bound_b are not equal.
The correct form would be more like this:

                // Arbitrarily give param candidates priority
                // over projection and object candidates.
                ObjectCandidate => true,
                ProjectionCandidate(_) => {
                    if let ProjectionCandidate(_) = other.candidate {
                        false
                    } else {
                        true
                    }
                },
@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jul 18, 2016

I guess that you didn't just call filter, but are also packaging up the specific bound that was matched? Anyway, not having seen the full diff, the general direction of these changes make sense to me.

rozbb pushed a commit to rozbb/rust that referenced this issue Jul 19, 2016

rozbb pushed a commit to rozbb/rust that referenced this issue Jul 20, 2016

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jul 21, 2016

Related: #34912

@pnkfelix

This comment has been minimized.

Copy link
Member

pnkfelix commented Jul 21, 2016

triage: P-medium

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.