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

Generic bounds are used overzealously #82170

Closed
RustyYato opened this issue Feb 16, 2021 · 2 comments
Closed

Generic bounds are used overzealously #82170

RustyYato opened this issue Feb 16, 2021 · 2 comments
Labels
A-inference Area: Type inference A-traits Area: Trait system C-bug Category: This is a bug. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@RustyYato
Copy link
Contributor

RustyYato commented Feb 16, 2021

I tried this code:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d10a2b403aee136b0426cc7f602d51ef

pub trait Callable<A> {
    type Output;
}

pub struct Call<A>(A);

impl<F: FnOnce(A) -> B, A, B> Callable<F> for Call<A> {
    type Output = B;
}

impl<A> Call<A> {
    fn build<F>(f: F) -> impl FnOnce(A) -> <Self as Callable<F>>::Output
    where
        Self: Callable<F>
    {
        move |a| todo!()
    }
}

fn foo<F>(f: F)
where
    Call<()>: Callable<F>
{
    Call::build(Call::build(f));
}

fn bar() {
    Call::build(Call::build(|()| 0));
}

I expected it to compile, but it doesn't. Instead, I get the following compile error:

error[E0308]: mismatched types
  --> src/lib.rs:25:17
   |
13 |     fn build<F>(f: F) -> impl FnOnce(A) -> <Self as Callable<F>>::Output
   |                          ----------------------------------------------- the found opaque type
...
21 | fn foo<F>(f: F)
   |        - this type parameter
...
25 |     Call::build(Call::build(f));
   |                 ^^^^^^^^^^^^^^ expected type parameter `F`, found opaque type
   |
   = note: expected type parameter `F`
                 found opaque type `impl FnOnce<((),)>`
   = help: type parameters must be constrained to match other types
   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

This is unusual because Call::build is implemented for all types F: FnOnce(A) -> _ (through the Callable trait), and since Call::build returns a type that implements FnOnce(A) -> _, it should be possible to recursively call Call::bulid if the first one succeeds. However, Rust overzelously assumes that Call::build can only be called with F (the concrete type parameter) instead of any type that implements FnOnce(A) -> _. (I'm trying to abstract over Fn* traits for a single argument, so this is road bump is annoying to work around, it requires duplicating all applicable functions).

@RustyYato RustyYato added the C-bug Category: This is a bug. label Feb 16, 2021
@ChrisDenton ChrisDenton added the needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. label Jul 16, 2023
@fmease fmease added A-traits Area: Trait system A-inference Area: Type inference T-types Relevant to the types team, which will review and decide on the PR/issue. and removed needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. labels Jan 29, 2024
@fmease
Copy link
Member

fmease commented Jan 29, 2024

Possibly a duplicate of #24066?

@RustyYato
Copy link
Contributor Author

You're right! Nice find

@fmease fmease closed this as not planned Won't fix, can't repro, duplicate, stale Jan 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inference Area: Type inference A-traits Area: Trait system C-bug Category: This is a bug. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants