Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.expect( format!() ): expected `&str`, found struct `String`

Tags:

macros

rust

I tried to create a macro that replaces,

first: Some(first.as_ref().parse::<u64>().expect("'first' should be an unsigned integer"))

I've seen this done in other modules like Clap with values_t!, my attempt to abstract this doesn't extend to types. I wrote this,

macro_rules! parse_u64 {
  ($var:ident) => {
    Some(
      $var
      .as_ref()
      .parse::<u64>()
      .expect(  format!("'{:?}' should be an unsigned integer", stringify!($var))  )
    ) 
  };
}

This produces the following error,

first: parse_u64!(first),
       ^^^^^^^^^^^^^^^^^ expected `&str`, found struct `String`

What am I doing wrong here: this is a simple macro with only three things in the chain? Why do I get this error and how can I fix it?


You can see this in this Rust Playground example

like image 742
NO WAR WITH RUSSIA Avatar asked Jul 21 '26 09:07

NO WAR WITH RUSSIA


1 Answers

As you mentioned in your own answer, expect takes a &str so you can't pass in a String directly:

.expect(format!("'{:?}' should be an unsigned integer", stringify!($var)).as_str())

However, this will perform string formatting (and allocate a new string) even if there was no error, so instead I would propose this:

.unwrap_or_else(|err| panic!("'{:?}' should be an unsigned integer: {}", stringify!($var), err))

This is effectively the same as the above, expect that unwrap_or_else only invokes its closure in the error case.


Alternatively, in this specific case you can concatenate string literals at compile-time with concat!, which also avoids the cost of format!:

.expect(concat!("'", stringify!($var), "' should be an unsigned integer"))
like image 96
Frxstrem Avatar answered Jul 22 '26 23:07

Frxstrem