Cannot unify associated type in `impl Fn` with concrete type

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));
}

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?

Thanks for your help in advance :slight_smile:

This looks like a bug.

Thanks Rusty. I filed https://github.com/rust-lang/rust/issues/73226 as well now

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.