Fulfilling trait bound with blanket impl can cause associated type mismatch #112583
Labels
A-associated-items
Area: Associated items (types, constants & functions)
C-bug
Category: This is a bug.
fixed-by-next-solver
Fixed by the next-generation trait solver, `-Znext-solver`.
T-types
Relevant to the types team, which will review and decide on the PR/issue.
Hello,
I have two traits, one that is to be manually implemented by the user and the other, if the first was implemented in a valid way, is automatically blanket implemented on the same type.
If I bound that the first trait must also implement the second, so the compiler points out invalid implementations of it, certain situations can cause associated types to mismatches when they are actually the same.
Minimal code to replicate:
Causes this error:
On the Playground, while the result is the same on Nightly as well.
Workaround 1: Bound at caller site instead
One fix is to not bound
Bar
onFoo
.On the playground.
That has the downside that the compiler cannot point out invalid implementations of
Foo
before one attempts to use the type somewhere, where now the additional bound with+ Bar
has to be enforced.Workaround 2: Impl detail to trait bound
Another is to bound the types to match in the
Foo
bound already:On the playground.
This compiles and might be a solution for some, depending how the actual bounds look like.
This also limits users who want to manually implement
Bar
for their type where the associated types are not equal.Failing workaround 1: Another generic in the impl
One could attempt to bring in another generic into the implementation, but this makes the compiler complain as well and also suggest a solution that is not valid Rust:
On the Playground and here with the invalid suggestion. The behavior is again the same on Nightly here.
Failing workaround 2: Supertrait
Another attempt is using a super trait, but bounding
Foo
causes a cyclic recursion again, and bounding onlyBar
results in the super trait to be basically an alias of the top code with the same error.If one moves the bounds of the super trait to the impl, it compiles, but lacks the ability to access the implementations of
Foo
andBar
now. One would have to mirror both traits in here and this will cause the initial problem again, now in this third trait.My assumption is that the compiler within the blanket impl assumes that the trait is already implemented and calling
T::take_x(y);
considers an unspecific implementation where the types might not match.The text was updated successfully, but these errors were encountered: