Skip to content

Trait impls from where clauses (ParamEnv) take precedence over freestanding trait impls #24066

Open
@hanna-kruppe

Description

@hanna-kruppe

I stumbled upon this trying to write a function that generically takes a range (or something else with which str can be indexed), and slices a str with that range. I got that to work, this bug comes into play when the str is produced by slicing another string with a RangeFrom or another concrete type (in the same function).

Here's a simpler (no lifetimes, no associated types) and self-contained example (playpen):

trait Frobnicate<I> {
    fn frob(&self, i: I) -> Self;
}

struct Thing;

struct IA;
struct IB;

impl Frobnicate<IA> for Thing {
    fn frob(&self, _i: IA) -> Thing { Thing }
}

impl Frobnicate<IB> for Thing {
    fn frob(&self, _i: IB) -> Thing { Thing }
}

fn delegate_frob<I>(t: Thing, i: I) -> Thing
        where Thing : Frobnicate<I> {
    let t2: Thing = t.frob(IA);
    t2.frob(i)
}

fn main() {}

This seems innocent enough. There's a impl Frobnicate<IA> for Thing, so the .frob(IA) call should work, and it's known to return Thing again, so via the where clause the .frob(i) call is good as well. However, I get this error message:

<anon>:20:28: 20:30 error: mismatched types:
 expected `I`,
    found `IA`
(expected type parameter,
    found struct `IA`) [E0308]
<anon>:20     let t2: Thing = t.frob(IA);
                                     ^~

It appears that the where clause makes the compiler forget that there are other impls.
Adding a Thing : Frobnicate<IA> bound only makes the compiler (rightly) complain that that's not a bound at all, since it doesn't involve any type parameters.
UFCS makes it compile, though:

    let t2: Thing = <Thing as Frobnicate<IA>>::frob(&t, IA);

Edit: Besides playpen, I can also reproduce this locally:

rustc 1.0.0-beta (9854143cb 2015-04-02) (built 2015-04-02)
binary: rustc
commit-hash: 9854143cba679834bc4ef932858cd5303f015a0e
commit-date: 2015-04-02
build-date: 2015-04-02
host: x86_64-pc-windows-gnu
release: 1.0.0-beta

But I already noticed it a couple of weeks ago, so it can't be a recent regression.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-trait-systemArea: Trait systemC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions