Skip to content

Mismatched closure arguments are no longer expanded in rustc 1.64 and later #100690

Closed
@passy

Description

@passy

Sorry, this is not necessarily the smallest possible example. Please let me know if this is unhelpful and I'll come up with something more concise.

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8a1f669598035e38e7e141eb799d6738

use std::io;

fn real_dispatch<T, F>(f: F) -> Result<(), io::Error>
where
    F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static,
{
    todo!()
}

#[derive(Debug)]
struct UIView<'a, T: 'a> {
    _phantom: std::marker::PhantomData<&'a mut T>,
}

trait Handle<'a, T: 'a, V, R> {
    fn dispatch<F>(&self, f: F) -> Result<(), io::Error>
    where
        F: FnOnce(&mut V) -> R + Send + 'static;
}

#[derive(Debug, Clone)]
struct TUIHandle<T> {
    _phantom: std::marker::PhantomData<T>,
}

impl<'a, T: 'a> Handle<'a, T, UIView<'a, T>, Result<(), io::Error>> for TUIHandle<T> {
    fn dispatch<F>(&self, f: F) -> Result<(), io::Error>
    where
        F: FnOnce(&mut UIView<'a, T>) -> Result<(), io::Error> + Send + 'static,
    {
        real_dispatch(f)
    }
}

The output in current stable (1.63.0) is:

(Please note the "expected closure with ... found closure with ..." hint.)

error[E0277]: expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
  --> src/lib.rs:31:23
   |
31 |         real_dispatch(f)
   |         ------------- ^ expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
   |         |
   |         required by a bound introduced by this call
   |
   = note: expected a closure with arguments `(&mut UIView<'a, T>,)`
              found a closure with arguments `(&mut UIView<'_, T>,)`
note: required by a bound in `real_dispatch`
  --> src/lib.rs:5:8
   |
3  | fn real_dispatch<T, F>(f: F) -> Result<(), io::Error>
   |    ------------- required by a bound in this
4  | where
5  |     F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static,
   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error

From 1.64 onwards, the expected/found hint is omitted:

error[E0277]: expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
  --> src/lib.rs:31:23
   |
31 |         real_dispatch(f)
   |         ------------- ^ expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
   |         |
   |         required by a bound introduced by this call
   |
note: required by a bound in `real_dispatch`
  --> src/lib.rs:5:8
   |
3  | fn real_dispatch<T, F>(f: F) -> Result<(), io::Error>
   |    ------------- required by a bound in this
4  | where
5  |     F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static,
   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error

To me the 1.63 behaviour is preferable to that from 1.64+ as it can often be non-obvious where the differences lie.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsP-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-betaPerformance or correctness regression from stable to beta.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions