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

Cannot unify associated type parameter in impl Fn with concrete instantiation #73226

Open
rphmeier opened this issue Jun 11, 2020 · 1 comment
Labels
A-associated-items Area: Associated items such as associated types and consts. A-lazy-normalization Area: lazy normalization (tracking issue: #60471) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@rphmeier
Copy link
Contributor

rphmeier commented Jun 11, 2020

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 :)

@rphmeier rphmeier added the C-bug Category: This is a bug. label Jun 11, 2020
@jonas-schievink jonas-schievink added A-associated-items Area: Associated items such as associated types and consts. A-lazy-normalization Area: lazy normalization (tracking issue: #60471) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 11, 2020
@antonva
Copy link

antonva commented Jun 26, 2023

This seems to have been fixed at some point. Running the playground code works just fine on Stable 1.70.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-associated-items Area: Associated items such as associated types and consts. A-lazy-normalization Area: lazy normalization (tracking issue: #60471) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants