Skip to content

Rustc fails to infer appropriately general Fn* trait implementation in the face of complex HRTBs with GATs #99991

Open
@Aiden2207

Description

@Aiden2207

I tried this code:

#![feature(generic_associated_types)]
pub trait Func<'a, T> {
    type Output;
    fn invoke(&mut self, x: T) -> Self::Output;
}
impl<'a, T, U, F> Func<'a, T> for &'a mut F
where
    F: FnMut(T) -> U,
{
    type Output = U;
    fn invoke(&mut self, x: T) -> Self::Output {
        self(x)
    }
}
trait Foo {
    type Bar<'a>
    where
        Self: 'a;
    fn test<F>(f: F)
    where
        for<'a> &'a mut F: Func<'a, Self::Bar<'a>>;
}

impl Foo for () {
    type Bar<'a> = &'a ();
    fn test<F>(mut f: F)
    where
        for<'a> &'a mut F: Func<'a, Self::Bar<'a>>,
    {
        (&mut f).invoke(&());
    }
}
fn main() {
    let f: fn(&()) -> &() = |t| t;
    <()>::test(f); //works
    <()>::test(|t| t); //error
}

I expected to see this happen: Code compiles without errors.

Instead, this happened:

   Compiling playground v0.0.1 (/playground)
error: implementation of `FnOnce` is not general enough
  --> src/main.rs:33:5
   |
33 |     <()>::test(|t|t);  //error
   |     ^^^^^^^^^^ implementation of `FnOnce` is not general enough
   |
   = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
   = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`

error: could not compile `playground` due to previous error

Playground

The compiler needs closures to be explicitly coerced into a general enough type for the provided trait bounds to work. It's not the end of the world, because I can always use trait objects, but it's definitely an ergonomic issue. Also, it works just fine if you use a non-generic associated type.

Meta

Playground version:

1.64.0-nightly

(2022-07-30 0f4bcadb46006bc484da)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-GATsArea: Generic associated types (GATs)A-closuresArea: Closures (`|…| { … }`)A-higher-rankedArea: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)A-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.T-typesRelevant to the types 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

    Issue actions