Skip to content

FnMut not implemented for mutable FnMut implementors #23015

Closed

Description

@alexcrichton

For example this program does not compile

fn foo<F: FnMut()>(_: F) {}

fn main() {
    let mut cb = || {};
    foo(&mut cb);
}
foo.rs:5:5: 5:8 error: the trait `core::ops::Fn<()>` is not implemented for the type `&mut [closure foo.rs:4:18: 4:23]` [E0277]
foo.rs:5     foo(&mut cb);
             ^~~
error: aborting due to previous error

The unfortunate error message is covered by another issue, but this seems like an unfortunate limitation. I tried to implement this but got coherence violations. I also implemented this "halfway" and got compile errors due to legitimate coherence violations which sprang up. I believe we have some hardwired impls of these traits in the compiler, but I'd like to make sure we have our story straight on these.

Activity

  1. laijs commented on Mar 4, 2015

    @laijs

    These code can't work?:

    impl<T:FnMut> FnMut for &mut T { ... }
    impl<T:Fn> Fn for &T { ... }

    I know this will leave another four types without implmenting any Fn*.
    the left four types: &mut Fn, &FnMut, &FnOnce, &mut FnOnce

  2. theemathas commented on Mar 5, 2015

    @theemathas
    Contributor

    Already discussed in http://internals.rust-lang.org/t/implement-closure-traits-on-t-when-t-implements-them/1638

    You can workaround withfoo(||cb()) in most cases.

  3. pnkfelix commented on Mar 5, 2015

    @pnkfelix
    Contributor

    seems likely fixable in backwards compatible manner.

    P-high, not 1.0.

  4. nikomatsakis commented on Mar 5, 2015

    @nikomatsakis
    Contributor

    I'm working hard on this.

  5. nikomatsakis commented on Mar 17, 2015

    @nikomatsakis
    Contributor

    So I've implemented this but I found two surprising interactions.

    First, impls like FnMut for &mut F where F : FnMut conflict with the core/str/pattern impls. I fixed this by removing the "autoderef" Pattern impl and adding an impl of Pattern for &String.

    Second, the autoderef loop for calls, currently, always autorefs. This is because it's based around the operator code and not the normal method lookup. This probably needs to be changed though because otherwise if we have x: &mut F where F:FnMut, you can't call x() -- you have to declare mut x: &mut F. The reason is that x() gets elaborated to <&mut F as FnMut()>::call_mut(&mut x) rather than <F as FnMut()>::call_mut(&mut *x). The latter is what we get today and probably what we want.

  6. added a commit that references this issue on Mar 24, 2015
  7. added a commit that references this issue on Aug 10, 2026
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-closuresArea: Closures (`|…| { … }`)P-mediumMedium priority

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions