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

Unable to substitute Arc<dyn Fn> #259

Closed
kvark opened this issue Apr 24, 2022 · 5 comments
Closed

Unable to substitute Arc<dyn Fn> #259

kvark opened this issue Apr 24, 2022 · 5 comments

Comments

@kvark
Copy link
Contributor

kvark commented Apr 24, 2022

I have the following code using std::sync::Arc: https://github.com/kvark/choir/blob/6cb29be018a19135d947942aad37f42b47161e7b/src/lib.rs#L58

Arc<dyn Fn(SubIndex) + Send + Sync + 'static>,

Loom's Arc doesn't appear to support this:

error[E0277]: the size for values of type `(dyn Fn(u32) + Send + Sync + 'static)` cannot be known at compilation time
  --> src/lib.rs:68:9
   |
68 |         Arc<dyn Fn(SubIndex) + Send + Sync + 'static>,
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `(dyn Fn(u32) + Send + Sync + 'static)`
note: required by a bound in `loom::sync::Arc`
  --> /Users/kvark/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.4/src/sync/arc.rs:8:16
   |
8  | pub struct Arc<T> {
   |                ^ required by this bound in `loom::sync::Arc`
@taiki-e
Copy link
Member

taiki-e commented Apr 24, 2022

I believe this has been fixed in (unreleased) #226.

@kvark
Copy link
Contributor Author

kvark commented Apr 24, 2022

This is great! Unfortunately, it's not completely smooth yet. With Loom's Arc, I'm getting these errors:

error[E0308]: mismatched types
   --> src/lib.rs:360:62
    |
357 |         fun: impl Fn(SubIndex) + Send + Sync + 'static,
    |              ----------------------------------------- this type parameter
...
360 |         let task = self.create_task(Functor::Multi(0..count, Arc::new(fun)));
    |                                                              ^^^^^^^^^^^^^ expected trait object `dyn Fn`, found type parameter `impl Fn(SubIndex) + Send + Sync + 'static`
    |
    = note: expected struct `loom::sync::Arc<(dyn Fn(u32) + Send + Sync + 'static)>`
               found struct `loom::sync::Arc<impl Fn(SubIndex) + Send + Sync + 'static>`
    = help: type parameters must be constrained to match other types
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

I.e. Arc<impl Fn> can be cast (safely) to Arc<dyn Fn> but this doesn't occur with Loom.

@taiki-e
Copy link
Member

taiki-e commented Apr 24, 2022

Hmm, it can be worked around using Arc::from_std(std::sync::Arc::new, but it is not ideal.

@taiki-e
Copy link
Member

taiki-e commented Apr 24, 2022

That said, the behavior is actually well documented, the workaround is provided, and a fix would require the unstable feature.
So I don't think there is any action that can be taken on our side at this time.

loom/src/sync/arc.rs

Lines 34 to 77 in d0c1e71

/// Converts `std::sync::Arc` to `loom::sync::Arc`.
///
/// This is needed to create a `loom::sync::Arc<T>` where `T: !Sized`.
///
/// ## Panics
///
/// If the provided `Arc` has copies (i.e., if it is not unique).
///
/// ## Examples
///
/// While `std::sync::Arc` with `T: !Sized` can be created by coercing an
/// `std::sync::Arc` with a sized value:
///
/// ```rust
/// let sized: std::sync::Arc<[u8; 3]> = std::sync::Arc::new([1, 2, 3]);
/// let _unsized: std::sync::Arc<[u8]> = sized; // coercion
/// ```
///
/// `loom::sync::Arc` can't be created in the same way:
///
/// ```compile_fail,E0308
/// use loom::sync::Arc;
///
/// let sized: Arc<[u8; 3]> = Arc::new([1, 2, 3]);
/// let _unsized: Arc<[u8]> = sized; // error: mismatched types
/// ```
///
/// This is because `std::sync::Arc` uses an unstable trait called `CoerceUnsized`
/// that loom can't use. To create `loom::sync::Arc` with an unsized inner value
/// first create a `std::sync::Arc` of an appropriate type and then use this method:
///
/// ```rust
/// use loom::sync::Arc;
///
/// # loom::model::model(|| {
/// let std: std::sync::Arc<[u8]> = std::sync::Arc::new([1, 2, 3]);
/// let loom: Arc<[u8]> = Arc::from_std(std);
///
/// let std: std::sync::Arc<dyn Send + Sync> = std::sync::Arc::new([1, 2, 3]);
/// let loom: Arc<dyn Send + Sync> = Arc::from_std(std);
/// # });
/// ```
#[track_caller]
pub fn from_std(mut std: std::sync::Arc<T>) -> Self {

@Darksonn
Copy link
Contributor

I'm going to close this for now.

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