Navigation Menu

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

Unboxed closure + traits bug #18453

Closed
carllerche opened this issue Oct 30, 2014 · 6 comments · Fixed by #18494
Closed

Unboxed closure + traits bug #18453

carllerche opened this issue Oct 30, 2014 · 6 comments · Fixed by #18494
Assignees

Comments

@carllerche
Copy link
Member

I am not exactly sure what is going on in this bug, so sorry for the vague title. I do have a repro though. The highlighted clone is what causes the issue here.

#![feature(unboxed_closures)]

use std::sync::Arc;

pub trait Foo<M: Send> : Send {
    fn foo(&mut self, msg: M);
}

impl<M: Send, F: Send + FnMut(M)> Foo<M> for F {
    fn foo(&mut self, msg: M) {
        self.call_mut((msg,));
    }
}

pub struct Both<M, F> {
    inner: Arc<(M, F)>,
}

impl<M: Send, F: Foo<M>> Clone for Both<M, F> {
    fn clone(&self) -> Both<M, F> {
        Both { inner: self.inner.clone() }
    }
}

fn repro1<M: Send, F: Foo<M>>(_both: Both<M, F>) {
}

fn repro2<M: Send + Sync, F: Sync + Foo<M>>(msg: M, foo: F) {
    let both = Both { inner: Arc::new((msg, foo)) };
    repro1(both.clone()); // <--- This clone causes problem
}

pub fn main() {
    println!("hello");
}

Gives me the following output:

rustc fnmut.rs
fnmut.rs:30:5: 30:11 error: the trait `core::ops::FnMut<(M),()>` is not implemented for the type `F`
fnmut.rs:30     repro1(both.clone()); // <--- This clone causes problem
                ^~~~~~
fnmut.rs:30:5: 30:11 note: the trait `core::ops::FnMut` must be implemented because it is required by `repro1`
fnmut.rs:30     repro1(both.clone()); // <--- This clone causes problem
                ^~~~~~
error: aborting due to previous error
@carllerche
Copy link
Member Author

For what it is worth, I was wondering if the Sync requirement was the problem, but it did not seem to be. The following produces the same error. Note the addition of UnsafeCell and the removal of the Sync bound.

#![feature(unboxed_closures)]

use std::cell::UnsafeCell;
use std::sync::Arc;

pub trait Foo<M: Send> : Send {
    fn foo(&mut self, msg: M);
}

impl<M: Send, F: Send + FnMut(M)> Foo<M> for F {
    fn foo(&mut self, msg: M) {
        self.call_mut((msg,));
    }
}

pub struct Both<M, F> {
    inner: Arc<UnsafeCell<(M, F)>>,
}

impl<M: Send, F: Foo<M>> Clone for Both<M, F> {
    fn clone(&self) -> Both<M, F> {
        Both { inner: self.inner.clone() }
    }
}

fn repro1<M: Send, F: Foo<M>>(_both: Both<M, F>) {
}

fn repro2<M: Send, F: Foo<M>>(msg: M, foo: F) {
    let both = Both { inner: Arc::new(UnsafeCell::new((msg, foo))) };
    repro1(both.clone()); // <--- This clone causes problem
}

pub fn main() {
    println!("hello");
}

@aturon aturon mentioned this issue Oct 30, 2014
47 tasks
@nikomatsakis
Copy link
Contributor

Maybe a dup of #16929

@nikomatsakis
Copy link
Contributor

or maybe not

@nikomatsakis
Copy link
Contributor

cc me -- not clear to me that this is related to unboxed closures, though it might have to do with the semi-special treatment that FnMut receives in trait matching

@nikomatsakis
Copy link
Contributor

I suspect what's happening is that the trait matching logic that chooses impls over where clauses is making an incorrect choice here.

@carllerche
Copy link
Member Author

Just so that I can find it again, PR #18388 adds blanket impls to allow the various Fn traits to be interconverted.

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

Successfully merging a pull request may close this issue.

2 participants