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

Error with autoderef on newtype wrapping FnMut #26186

Closed
eefriedman opened this issue Jun 10, 2015 · 7 comments · Fixed by #92303
Closed

Error with autoderef on newtype wrapping FnMut #26186

eefriedman opened this issue Jun 10, 2015 · 7 comments · Fixed by #92303
Labels
A-type-system Area: Type system C-bug Category: This is a bug.

Comments

@eefriedman
Copy link
Contributor

Testcase:

use std::ops::*;
struct S<'a, T:FnMut() + 'static + ?Sized>(&'a mut T);
impl<'a, T:?Sized + FnMut() + 'static> DerefMut for S<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
impl<'a, T:?Sized + FnMut() + 'static> Deref for S<'a, T> {
    type Target = FnMut() + 'a;
    fn deref(&self) -> &Self::Target { &self.0 }
}
fn main() {
    let mut f = ||{};
    let mut s = S(&mut f);
    s();
}

Yields:

<anon>:13:5: 13:6 error: cannot borrow immutable borrowed content as mutable
<anon>:13     s();
              ^

Auto-deref should be picking DerefMut here, not Deref.

@Diggsey
Copy link
Contributor

Diggsey commented Sep 10, 2016

I just ran into this problem too, here's a shorter example:

use std::cell::RefCell;
use std::rc::Rc;

struct Foo(Rc<RefCell<FnMut()>>);

fn main() {
    let a = Foo(Rc::new(RefCell::new(||{
        println!("Hello, world!");
    })));
    a.0.borrow_mut()();
}

And playpen link: https://is.gd/KQJ9ij

@Mark-Simulacrum
Copy link
Member

Further reduced:

use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let a: Rc<RefCell<FnMut()>> = Rc::new(RefCell::new(||{}));
    a.borrow_mut()();
}

@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 22, 2017
@shepmaster
Copy link
Member

Another example from Stack Overflow:

use std::ops::{Deref, DerefMut};

struct Foo;

impl Deref for Foo {
    type Target = FnMut() + 'static;
    fn deref(&self) -> &Self::Target {
        unimplemented!()
    }
}

impl DerefMut for Foo {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unimplemented!()
    }
}

fn main() {
    let mut t = Foo;
    t();
}

@shepmaster
Copy link
Member

And again experienced on Stack Overflow

@frankmcsherry
Copy link
Contributor

Just got this today, with what is almost identical to Mark-Simulacrum's reduced version.

@Osspial
Copy link

Osspial commented Jul 11, 2020

I've also run into this issue, with this example:

use std::sync::Mutex;

struct FunctionIcon {
    get_icon: Mutex<Box<dyn FnMut() -> u32>>,
}

impl FunctionIcon {
    fn get_icon(&self) -> impl '_ + std::ops::DerefMut<Target=Box<dyn FnMut() -> u32>> {
        self.get_icon.lock().unwrap()
    }
    
    fn load_icon(&self)  {
        let mut get_icon = self.get_icon();
        let rgba_icon = (*get_icon)();
    }
}

and this error:

error[E0596]: cannot borrow data in a dereference of `impl std::ops::DerefMut` as mutable
  --> src/lib.rs:14:25
   |
14 |         let rgba_icon = (*get_icon)();
   |                         ^^^^^^^^^^^ cannot borrow as mutable
   |
   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `impl std::ops::DerefMut`

@Patrick-Poitras
Copy link
Contributor

Patrick-Poitras commented Dec 26, 2021

This error seems resolved. Examples above all work on stable.

Patrick-Poitras added a commit to Patrick-Poitras/rust that referenced this issue Dec 27, 2021
bors added a commit to rust-lang-ci/rust that referenced this issue Dec 27, 2021
…askrgr

Rollup of 7 pull requests

Successful merges:

 - rust-lang#90586 (Relax priv-in-pub lint on generic bounds and where clauses of trait impls.)
 - rust-lang#92112 (Fix the error of checking `base_expr` twice in type_changing_struct_update)
 - rust-lang#92147 (rustc_builtin_macros: make asm mod public for rustfmt)
 - rust-lang#92161 (resolve: Minor miscellaneous cleanups from rust-lang#89059)
 - rust-lang#92264 (Remove `maybe_uninit_extra` feature from Vec docs)
 - rust-lang#92303 (Add test cases for issue rust-lang#26186)
 - rust-lang#92307 (Fix minor typos)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors closed this as completed in 052eab5 Dec 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-type-system Area: Type system C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants