Skip to content

Trait bound on associated type causes confusing compilation error #58231

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

Open
igowen opened this issue Feb 6, 2019 · 3 comments
Open

Trait bound on associated type causes confusing compilation error #58231

igowen opened this issue Feb 6, 2019 · 3 comments
Labels
A-associated-items Area: Associated items (types, constants & functions) A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@igowen
Copy link

igowen commented Feb 6, 2019

This code fails to compile:

pub trait Append<T> {
    type Appended;
}

pub trait Proc {
    type Item;
    type Tail;
    fn process_item<P>(&mut self, partial: P)
    where
        P: Append<Self::Item>,
        P::Appended: Append<Self::Tail>;
}

struct Read;

impl Proc for Read {
    type Item = i32;
    type Tail = i64;
    fn process_item<P>(&mut self, partial: P)
    where
        P: Append<Self::Item>,
        P::Appended: Append<Self::Tail>,
    {
        
    }
}
error[E0277]: the trait bound `P: Append<i32>` is not satisfied
  --> src/lib.rs:19:5
   |
19 | /     fn process_item<P>(&mut self, partial: P)
20 | |     where
21 | |         P: Append<Self::Item>,
22 | |         P::Appended: Append<Self::Tail>,
23 | |     {
24 | |         
25 | |     }
   | |_____^ the trait `Append<i32>` is not implemented for `P`
   |
   = help: consider adding a `where P: Append<i32>` bound

The error is confusing because Self::Item is i32. Furthermore, changing the bound on P to the suggested bound (setting aside the fact that this is a trait impl so imposing additional bounds isn't necessarily appropriate) yields an even more confusing error:

error[E0277]: the trait bound `P: Append<i32>` is not satisfied
  --> src/lib.rs:19:5
   |
19 | /     fn process_item<P>(&mut self, partial: P)
20 | |     where
21 | |         P: Append<i32>,
22 | |         P::Appended: Append<Self::Tail>,
23 | |     {
24 | |         
25 | |     }
   | |_____^ the trait `Append<i32>` is not implemented for `P`
   |
   = help: consider adding a `where P: Append<i32>` bound

error[E0276]: impl has stricter requirements than trait
  --> src/lib.rs:19:5
   |
8  | /     fn process_item<P>(&mut self, partial: P)
9  | |     where
10 | |         P: Append<Self::Item>,
11 | |         P::Appended: Append<Self::Tail>;
   | |________________________________________- definition of `process_item` from trait
...
19 | /     fn process_item<P>(&mut self, partial: P)
20 | |     where
21 | |         P: Append<i32>,
22 | |         P::Appended: Append<Self::Tail>,
23 | |     {
24 | |         
25 | |     }
   | |_____^ impl has extra requirement `P: Append<i32>`

error: aborting due to 2 previous errors

Adding an additional type parameter to the fn and using that as the bound on P::Appended appears to work fine, and i think it is semantically equivalent (although applying the bound directly to the associated type is cleaner IMO):

pub trait Append<T> {
    type Appended;
}

pub trait Proc {
    type Item;
    type Tail;
    fn process_item<P, T>(&mut self, partial: P)
    where
        P: Append<Self::Item, Appended = T>,
        T: Append<Self::Tail>;
}

struct Read;

impl Proc for Read {
    type Item = i32;
    type Tail = i64;
    fn process_item<P, T>(&mut self, partial: P)
    where
        P: Append<i32, Appended = T>,
        T: Append<Self::Tail>,
    {

    }
}

Should the original code compile? If not, the error message (and suggested fix) is monumentally unhelpful. Otherwise, if it should compile, this looks like a compiler bug.

@jonas-schievink jonas-schievink added A-diagnostics Area: Messages for errors, warnings, and lints A-associated-items Area: Associated items (types, constants & functions) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 6, 2019
@igowen
Copy link
Author

igowen commented Feb 6, 2019

also found #57905 & #32722 which seem similar but it's unclear to me if they are the same underlying issue.

@estebank
Copy link
Contributor

Triage, little change:

error[E0277]: the trait bound `P: Append<i32>` is not satisfied
  --> file12.rs:19:5
   |
19 | /     fn process_item<P>(&mut self, partial: P)
20 | |     where
21 | |         P: Append<Self::Item>,
22 | |         P::Appended: Append<Self::Tail>,
   | |                                         - help: consider further restricting type parameter `P`: `, P: Append<i32>`
23 | |     {
24 | |
25 | |     }
   | |_____^ the trait `Append<i32>` is not implemented for `P`

@cynecx
Copy link
Contributor

cynecx commented Feb 25, 2023

Got curious. Tested this (and some other test cases from different issues) under the new -Ztrait-solver=next feature and it seems work 😱.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-associated-items Area: Associated items (types, constants & functions) A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants