Description
Hi!
I recently experienced a bug in that probably comes from problems of the interference of type inference, impl Trait in return type position, and associated types.
This is a very strongly simplified version of what was going on in my codebase. In fact my codebase included Arc
instead of SmartPointer
and AsRef
instead of MyAsRef
, but I wanted to simplify to reproduce the problem without std
.
struct SmartPointer<A>(A);
trait MyAsRef<A> {
fn my_ref(&self) -> &A;
}
impl<A> MyAsRef<A> for SmartPointer<A> {
fn my_ref(&self) -> &A {
&self.0
}
}
struct Type0Container<P>(SmartPointer<P::Type0>)
where
P: TypeSet;
impl<P> Type0Container<P>
where
P: TypeSet,
{
// fn item(&self) -> &SmartPointer<P::Type0> { // << compiles
fn item(&self) -> &impl MyAsRef<P::Type0> { // << does not compile
&self.0
}
}
trait TypeSet {
type Type0;
}
struct TypeSetImpl;
struct Type0Impl;
impl TypeSet for TypeSetImpl {
type Type0 = Type0Impl;
}
fn main() {
let proc: Type0Container<TypeSetImpl> = Type0Container(SmartPointer(Type0Impl));
let _: &Type0Impl = proc.item().my_ref();
}
I expected to see this happen:
The compiler should be able to infer that <TypeSetImpl as TypeSet>::Type0
= Type0Impl
and compile the program.
Instead, this happened:
The compiler failed with this error message:
Compiling lala v0.1.0 (/path/to/lala)
error[E0308]: mismatched types
--> src/main.rs:41:25
|
41 | let _: &Type0Impl = proc.item().my_ref();
| ---------- ^^^^^^^^^^^^^^^^^^^^ expected struct `Type0Impl`, found associated type
| |
| expected due to this
|
= note: expected reference `&Type0Impl`
found reference `&<TypeSetImpl as TypeSet>::Type0`
= help: consider constraining the associated type `<TypeSetImpl as TypeSet>::Type0` to `Type0Impl`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
As noted in the comments in the code snipped changing the one line using impl Trait in return type position enables the compiler to build the program.
I'm not entirely sure if this is a bug or if I expecting type inference to be stronger as it is or if the code I wrote is indeed not correct, so sorry if that is the case.
Meta
rustc --version --verbose
:
rustc 1.46.0-nightly (449e8eaa2 2020-06-10)
binary: rustc
commit-hash: 449e8eaa286e407c9cd8cac655b77998fd53db6b
commit-date: 2020-06-10
host: x86_64-apple-darwin
release: 1.46.0-nightly
LLVM version: 10.0
None
<backtrace>