Skip to content

Asssociated type declared in where clause is not enforced in type parameter #116864

Closed
@c410-f3r

Description

@c410-f3r
Contributor

For some reason FnMutFut<&'any BAZ::Param, ()> is not being inferred as FnMutFut<&'any i32, ()>, which results in an unsatisfied trait bound error.

use std::future::Future;

pub trait Baz {
    type Param;
}

pub trait FnMutFut<P, R>: FnMut(P) -> Self::Future {
    type Future: Future<Output = R>;
}

impl<P, F, FUT, R> FnMutFut<P, R> for F
where
    F: FnMut(P) -> FUT,
    FUT: Future<Output = R>,
{
    type Future = FUT;
}

pub async fn does_not_work<BAZ>(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>)
where
    BAZ: Baz<Param = i32>,
{
    cb(&1i32).await;
}

Perhaps something involving the generic implementation of FnMutFut? Perhaps something involving impl trait?

Activity

added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Oct 17, 2023
fmease

fmease commented on Oct 17, 2023

@fmease
Member

With -Ztrait-solver=classic:

error[E0277]: expected a `FnMut<(&'any i32,)>` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>`
  --> qq.rs:30:1
   |
30 | / pub async fn does_not_work<BAZ>(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>)
31 | | where
32 | |     BAZ: Baz<Param = i32>,
   | |__________________________^ expected an `FnMut<(&'any i32,)>` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>`
   |
   = note: expected a closure with arguments `(&<BAZ as Baz>::Param,)`
              found a closure with arguments `(&'any i32,)`
note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `for<'any> FnMutFut<&'any i32, ()>`
  --> qq.rs:22:20
   |
22 | impl<P, F, FUT, R> FnMutFut<P, R> for F
   |                    ^^^^^^^^^^^^^^     ^
23 | where
24 |     F: FnMut(P) -> FUT,
   |        --------------- unsatisfied trait bound introduced here

With -Ztrait-solver=next:

error[E0282]: type annotations needed
  --> qq.rs:34:13
   |
34 |     let _ = cb(&1i32).await;
   |             ^^^^^^^^^^^^^^^ cannot infer type

error[E0275]: overflow evaluating the requirement `<impl for<'any> FnMutFut<&'any BAZ::Param, ()> as FnMutFut<&<BAZ as Baz>::Param, ()>>::Future`
  |
  = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`qq`)
added
A-associated-itemsArea: Associated items (types, constants & functions)
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
A-lifetimesArea: Lifetimes / regions
and removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Oct 17, 2023
c410-f3r

c410-f3r commented on Oct 17, 2023

@c410-f3r
ContributorAuthor

Thank you @fmease!

Since you are here, would you mind taking a look at #116749? :)

lcnr

lcnr commented on Nov 13, 2023

@lcnr
Contributor

minimized

use std::future::Future;

pub trait Baz {
    type Param;
}

pub trait FnMutFut<P, R>: FnMut(P) -> Self::Future {
    type Future: Future<Output = R>;
}

impl<P, F, FUT, R> FnMutFut<P, R> for F
where
    F: FnMut(P) -> FUT,
    FUT: Future<Output = R>,
{
    type Future = FUT;
}

pub fn does_not_work<T, F>(mut cb: F)
where
    T: Baz<Param = i32>,
    F: FnMutFut<T::Param, ()>,
{}

which is a duplicate of #41118, the overflow error with -Ztrait-solver=next in the original example is interesting however. See the next comment

lcnr

lcnr commented on Nov 13, 2023

@lcnr
Contributor
use std::future::Future;

pub trait Baz {
    type Param;
}

pub trait FnMutFut<P, R>: FnMut(P) -> Self::Future {
    type Future: Future<Output = R>;
}

impl<P, F, FUT, R> FnMutFut<P, R> for F
where
    F: FnMut(P) -> FUT,
    FUT: Future<Output = R>,
{
    type Future = FUT;
}

pub fn does_not_work<T, F>(mut cb: F)
where
    T: Baz<Param = i32>,
    F: FnMutFut<T::Param, ()>,
{
    cb(1)
}

this results in overflow in the new solver during typeck https://rust.godbolt.org/z/GGWeh597M

further minimized this issue in rust-lang/trait-system-refactor-initiative#76. Therefore closing this issue as a duplicate. Thank you for discovering a new issue in the new solver 🎉 we've been unsure about rust-lang/trait-system-refactor-initiative#12 for quite a while and this is really useful

c410-f3r

c410-f3r commented on Nov 13, 2023

@c410-f3r
ContributorAuthor

@lcnr Thank you very much for investigating this use-case!

For further context, the code was based on a suggestion provided by @danielhenrymantilla to simulate fn fun(_: for<'a> impl Fn(&'a Foo) -> impl Bar + 'a).

3 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-associated-itemsArea: Associated items (types, constants & functions)A-lifetimesArea: Lifetimes / regionsA-trait-systemArea: Trait systemC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @fmease@c410-f3r@lcnr@rustbot

        Issue actions

          Asssociated type declared in `where` clause is not enforced in type parameter · Issue #116864 · rust-lang/rust