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

Cannot call a Vec<Box<Fn()>> without explicit dereferencing #36786

Closed
shepmaster opened this issue Sep 27, 2016 · 3 comments
Closed

Cannot call a Vec<Box<Fn()>> without explicit dereferencing #36786

shepmaster opened this issue Sep 27, 2016 · 3 comments

Comments

@shepmaster
Copy link
Member

This code works:

fn main() {
    let func: Box<Fn()> = Box::new(|| println!("called"));
    func();
}

As does placing it in an array:

fn main() {
    let func: [Box<Fn()>; 1] = [Box::new(|| println!("called"))];
    func[0]();
}

However, using a Vec fails:

fn main() {
    let func: Vec<Box<Fn()>> = vec![Box::new(|| println!("called"))];
    func[0](); // error: expected function, found `Box<std::ops::Fn()>`
}

Instead, it must be explicitly dereferenced:

fn main() {
    let func: Vec<Box<Fn()>> = vec![Box::new(|| println!("called"))];
    (*func[0])();
}

It's even more annoying for Vec<Box<FnMut()>>:

fn main() {
    let mut func: Vec<Box<FnMut()>> = vec![Box::new(|| println!("called"))];
    // func[0](); // expected function, found `Box<std::ops::FnMut()>`
    // (*func[0])(); // cannot borrow immutable `Box` content as mutable
    (*&mut func[0])();
}
@Aatch
Copy link
Contributor

Aatch commented Sep 29, 2016

The fact that this works for arrays, but not Vec suggests that it's probably related to associated types. It's possible that wherever the coercion from &Box<Fn()> to &Fn() is done sees &<Vec<Box<Fn()>> as Index<usize>>::Output instead.

Aatch added a commit to Aatch/rust that referenced this issue Sep 29, 2016
If the callee type is an associated type, then it needs to be normalized
before trying to deref it. This matches the behaviour of
`check_method_call` for autoderef behaviour in calls.

Fixes rust-lang#36786
bors added a commit that referenced this issue Sep 30, 2016
Resolve the callee type in check_call before autoderef

If the callee type is an associated type, then it needs to be normalized
before trying to deref it. This matches the behaviour of
`check_method_call` for autoderef behaviour in calls.

Fixes #36786
jakllsch pushed a commit to jakllsch/rust that referenced this issue Oct 1, 2016
If the callee type is an associated type, then it needs to be normalized
before trying to deref it. This matches the behaviour of
`check_method_call` for autoderef behaviour in calls.

Fixes rust-lang#36786
@jonhoo
Copy link
Contributor

jonhoo commented Mar 7, 2017

This doesn't seem to be fully resolved:

use std::sync::Mutex;

pub struct Foo(Mutex<Box<FnMut()>>);

impl Foo {
    pub fn foo(&self) {
        // self.0.lock().unwrap()(); // cannot borrow immutable `Box` content as mutable
        // (*self.0.lock().unwrap())(); // cannot borrow immutable `Box` content as mutable
        // (&mut self.0.lock().unwrap())(); // cannot borrow immutable `Box` content as mutable
        (&mut *self.0.lock().unwrap())();
    }
}

fn main() {
    Foo(Mutex::new(Box::new(|| println!("called")))).foo()
}

@shepmaster
Copy link
Member Author

@jonhoo That may be #26186 instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants