Description
Hi, I'm running into a strange behavior where the compiler has difficulty unifying an associated type in an impl Fn
with a concrete type in a certain instantiation of it.
Link to playpen: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1d0d2fd109dd2c691f2b2051b8a2d33a
I have also reproduced the code below.
trait Trait {
type Num: Copy;
}
struct NumIsU32;
impl Trait for NumIsU32 {
type Num = u32;
}
struct Foo<T>(std::marker::PhantomData<T>);
impl<T: Trait> Foo<T> {
fn make_predicate() -> impl Fn(T::Num) -> bool {
|num| true
}
fn make_predicate_boxed() -> Box<dyn Fn(T::Num) -> bool> {
Box::new(|num| true)
}
}
type FooForYou = Foo<NumIsU32>;
fn main() {
// doesn't compile: can't reconcile u32 with <NumIsU32 as Trait>::Num
// let pred = FooForYou::make_predicate();
// assert!(pred(5u32));
// does compile.
let pred = FooForYou::make_predicate_boxed();
assert!(pred(5u32));
}
Here is the error output for the portion that doesn't compile:
error[E0308]: mismatched types
--> src/main.rs:27:18
|
27 | assert!(pred(5u32));
| ^^^^ expected associated type, found `u32`
|
= note: expected associated type `<NumIsU32 as Trait>::Num`
found type `u32`
= note: consider constraining the associated type `<NumIsU32 as Trait>::Num` to `u32` or calling a method that returns `<NumIsU32 as Trait>::Num`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0277]: expected a `std::ops::Fn<(u32,)>` closure, found `impl std::ops::Fn<(<NumIsU32 as Trait>::Num,)>`
--> src/main.rs:27:13
|
27 | assert!(pred(5u32));
| ^^^^^^^^^^ expected an `Fn<(u32,)>` closure, found `impl std::ops::Fn<(<NumIsU32 as Trait>::Num,)>`
|
= help: the trait `std::ops::Fn<(u32,)>` is not implemented for `impl std::ops::Fn<(<NumIsU32 as Trait>::Num,)>`
error: aborting due to 2 previous errors
What is unclear to me is whether this is an intended restriction of the impl Trait
feature or an unintended compiler issue. I believe specialization imposes some artificial restrictions on unifying specialized associated types with their concrete counterparts as a soundness protection. Is the same happening here?
I have also posted this on the users.rust-lang-org forum where it was suggested this is a bug.
Thanks for your help in advance :)