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

Associated type equality not followed through multiple traits #34257

Open
sgrif opened this issue Jun 13, 2016 · 2 comments
Open

Associated type equality not followed through multiple traits #34257

sgrif opened this issue Jun 13, 2016 · 2 comments
Labels
A-type-system Area: Type system C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@sgrif
Copy link
Contributor

sgrif commented Jun 13, 2016

Simplest case to reproduce would be to add a trait which decorates IntoIterator and try to write a blanket impl for that trait:

trait DecoratesIntoIterator: IntoIterator {
    type Output: Iterator<Item=Self::Item>;
}

impl<T> DecoratesIntoIterator for T where
    T: IntoIterator,
    T::IntoIter: DecoratesIntoIterator,
{
    type Output = <T::IntoIter as DecoratesIntoIterator>::Output;
}

Will fail to compile with

type mismatch resolving `<<<T as std::iter::IntoIterator>::IntoIter as DecoratesIntoIterator>::Output as std::iter::Iterator>::Item == <T as std::iter::IntoIterator>::Item`:

even though every trait mentioned has the constraint that the output has Iterator<Item=Self::Item>.

Ran into this with a more concrete use case inside of Diesel:

trait Query {
    type SqlType;
}

trait AsQuery {
    type SqlType;
    type Query: Query<SqlType=Self::SqlType>;

    fn as_query(self) -> Self::Query;
}

trait LimitDsl: AsQuery {
    type Output: Query<SqlType=Self::SqlType>;

    fn limit(self, limit: i64) -> Self::Output;
}

impl<T> LimitDsl for T where
    T: AsQuery,
    T::Query: LimitDsl,
{
    type Output = <T::Query as LimitDsl>::Output;

    fn limit(self, limit: i64) -> Self::Output {
        self.as_query().limit(limit)
    }
}

This can be worked around by manually restating the constraint, like so:

impl<T, ST> LimitDsl for T where
    T: AsQuery<SqlType=ST>,
    T::Query: LimitDsl<SqlType=ST>,

but this shouldn't be required.

sgrif added a commit to diesel-rs/diesel that referenced this issue Jun 13, 2016
There were two goals here:

- Consistently put the constraint `AsQuery` on the output type. Many
  traits were using no bound or `Query` as the bound
- Enforce that the SQL type can't change for DSLs which shouldn't change
  the output type (which is basically everything except select and
  joins)

We shouldn't have to specify `SqlType=ST` in so many places, but we have
to do it here to work around
rust-lang/rust#34257.

As part of this, I've also done the same cleanup of `LoadDsl` that we
did to `FindDsl` in #352, moving as many where clause constraints as
possible off of the trait definition and into the impl. This let us
implement `first` purely in terms of `limit` and methods from `LoadDsl`,
with a more reasonable where clause on that method. `first` was the only
place that referenced `LimitDsl` generically in our code base, and was
the original motivation for this change.
sgrif added a commit to diesel-rs/diesel that referenced this issue Jun 13, 2016
There were two goals here:

- Consistently put the constraint `AsQuery` on the output type. Many
  traits were using no bound or `Query` as the bound
- Enforce that the SQL type can't change for DSLs which shouldn't change
  the output type (which is basically everything except select and
  joins)

We shouldn't have to specify `SqlType=ST` in so many places, but we have
to do it here to work around
rust-lang/rust#34257.

As part of this, I've also done the same cleanup of `LoadDsl` that we
did to `FindDsl` in #352, moving as many where clause constraints as
possible off of the trait definition and into the impl. This let us
implement `first` purely in terms of `limit` and methods from `LoadDsl`,
with a more reasonable where clause on that method. `first` was the only
place that referenced `LimitDsl` generically in our code base, and was
the original motivation for this change.
@TimNN
Copy link
Contributor

TimNN commented Jun 13, 2016

I believe that this may have the same cause as #25409 (the "This can be worked around by manually restating the constraint" sounds familiar at least), event though the issue manifests itself in a different way here.

@Mark-Simulacrum Mark-Simulacrum added A-type-system Area: Type system T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 23, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 25, 2017
@steveklabnik
Copy link
Member

Triage; still reproduces

@fmease fmease added A-type-system Area: Type system T-types Relevant to the types team, which will review and decide on the PR/issue. and removed A-type-system Area: Type system labels Dec 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-type-system Area: Type system C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants