Writing a generic number parsing function, but having an issue with the generic variable

⚓ Rust    📅 2025-10-17    👤 surdeus    👁️ 2      

surdeus

I am writing a function for an assembler parser I am writing to convert number tokens into an actual unsigned value. I wanted to write a generic version so that I might use it in future for different sizes.

At issue is the portion where I take a signed number and convert it to the same bit representation in unsigned (2's complement).

My thinking goes that all the implementations that I support have such cast_unsigned function, yet it cannot find it. Is there a proper way to do this?

I only see the impl directly on the concrete type no specific trait I could utilize.

use num_traits::{Num, Signed, Unsigned};

trait HasSignedEquivalent: Unsigned {
    type SignedEquivalent: Signed;
}

impl HasSignedEquivalent for u8 {
    type SignedEquivalent = i8;
}
impl HasSignedEquivalent for u16 {
    type SignedEquivalent = i16;
}

impl HasSignedEquivalent for u32 {
    type SignedEquivalent = i32;
}

impl HasSignedEquivalent for u64 {
    type SignedEquivalent = i64;
}

impl HasSignedEquivalent for u128 {
    type SignedEquivalent = i128;
}

impl HasSignedEquivalent for usize {
    type SignedEquivalent = isize;
}

pub fn parse_number<U: Unsigned + HasSignedEquivalent>(text: &str) -> Option<U> {
    if text.starts_with("-") {
        let element = U::SignedEquivalent::from_str_radix(text, 10);

        return match element {                      // no method named `cast_unsigned` found for associated type `<U as HasSignedEquivalent>::SignedEquivalent` in the current scope
            Ok(elem) => Some(elem.cast_unsigned()), // <-- cast_unsigned 
            Err(_) => None,
        }
    } else if text.starts_with("$") {
        let element = U::from_str_radix(&text[1..], 16);

        return match element {
            Ok(elem) => Some(elem),
            Err(_) => None,
        }
    } else if text.starts_with("%") {
        let element = U::from_str_radix(&text[1..], 2);

        return match element {
            Ok(elem) => Some(elem),
            Err(_) => None,
        }
    } else {
        let element = U::from_str_radix(text, 10);

        return match element {
            Ok(elem) => Some(elem),
            Err(_) => None,
        }
    }
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0599]: no method named `cast_unsigned` found for associated type `<U as HasSignedEquivalent>::SignedEquivalent` in the current scope
  --> src/lib.rs:35:35
   |
35 |             Ok(elem) => Some(elem.cast_unsigned()), // <-- cast_unsigned 
   |                                   ^^^^^^^^^^^^^ method not found in `<U as HasSignedEquivalent>::SignedEquivalent`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` (lib) due to 1 previous error

1 post - 1 participant

Read full topic

🏷️ Rust_feed