Obtain `Fixed{Signed, Unsigned}` from `Fixed` ("fixed" crate)

The "fixed" crate has 3 traits, that I'm going to use:

  • Fixed
  • FixedSigned (can't put more than 2 links in a post)
  • FixedUnsigned

I already have two functions:

fn process_signed<F: FixedSigned>(a: F) { !unimplemented() }
fn process_unsigned<F: FixedUnsigned>(a: F) { !unimplemented() }

I want to implement another function, whose purpose is to dispatch calls between two functions mentioned above:

fn dispatch<F: Fixed>(a: F) { !todo() }

I have tried the following:

fn dispatch<F: Fixed>(a: F) {
    if F::IS_SIGNED {
        let sig: FixedI64<<F as Fixed>::Frac> =
            FixedI64::<F::Frac>::from_bits(f.to_bits());
        // or
        let sig: <F as Fixed>::Unsigned =
            F::Signed::from_fixed(f);
        // Trait `FixedSigned` is not implemented for `F` [E0277]
        process_signed(sig)
    } else { !todo() }
}

Is it possible to make this working? I suspect that I am doing something completely wrong and there is an obvious simple and correct solution that I do not see at the moment.


Am I posting the question in the right place and category or is there a separate place for questions about crates? Perhaps I should find a way to contact the creator or create an issue in the crate's repository.

Wow, what a trait. There are Fixed::get_signed and Fixed::get_unsigned to obtain references to FixedSigned and FixedUnsigned types from something that implements Fixed. Are they of any help to you? They have equivalents for retrieving mutable references, too.

Yes, I have seen these methods, they give the same result as the second option I mentioned.
I wrote F::Signed::from_fixed() for clarity. get_signed().unwrap() gave me the same error. :disappointed_relieved:

More precisely, the type of the references they give is <F as Fixed>::Signed, for some reason this type doesn't consider as implementing FixedSigned. This is most likely the gist of my question. This doesn't even apply to a specific crate. I just don't understand much why this type can't be accepted.

This compiles on my machine:

fn process_signed<F: FixedSigned>(a: F) {
    unimplemented!()
}
fn process_unsigned<F: FixedUnsigned>(a: F) {
    unimplemented!()
}

fn dispatch<F: Fixed>(a: F) {
    process_signed(*a.get_signed().unwrap());
    process_unsigned(*a.get_unsigned().unwrap());
}

but I haven't found Copy as a supertrait of Fixed yet (which must be the reason why this compiles—Fixed must imply copy semantics on the implementing type or else we would get an error because we'd be trying to move out of a shared reference when we are passing the dereferenced value to one of the functions).

1 Like

You are absolutely right. Thank you for your time and patience. The problem turned out to be completely different, but you helped me by testing the example yourself and convincing me that I should look elsewhere.
I simply don't have the emotional strength left to create a separate project for testing this issue. Thank you for supporting me.
In case you're wondering, here's what the problem was. Comments on how to do this more idiomatically are welcome.

fn process_signed<F: FixedSigned>(a: &[F])
-> Result<Vec<F>, ProcessingError>
{ unimplemented!() }

fn dispatch<F: Fixed>(a: &[F])
-> Result<Vec<F>, ProcessingError>
{
    let ff = F::Signed::from_fixed;
    let a: Vec<_> = a.iter().copied().map(ff).collect();
    let r = process_signed(&a)?;
    // Return `Vec<F>` inside `Result`
    // where `F: FixedSigned`
    // but  expected `F: Fixed`
    return Ok(r) // wrong!
    Ok(r.into_iter().map(F::from_fixed).collect()) // nice!
}

Copy is a supertrait of at least Contiguous and Pod which are supertraits of Fixed.

3 Likes