46

I have this:

#[derive(FromPrimitive)]
pub enum MyEnum {
    Var1 = 1,
    Var2
}

And an error:

error: cannot find derive macro `FromPrimitive` in this scope                                                                                                 
   |                                                                                                                                                          
38 | #[derive(FromPrimitive)]                                                                                                                                 
   |          ^^^^^^^^^^^^^   

Why do I get this? How do I fix it?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
jerry
  • 827
  • 2
  • 7
  • 10

1 Answers1

46

The compiler has a small set of built-in derive macros. For any others, you have to import the custom derives before they can be used.

Before Rust 1.30, you need to use #[macro_use] on the extern crate line of the crate providing the macros. With Rust 1.30 and up, you can use them instead.

In this case, you need to import FromPrimitive from the num_derive crate:

After Rust 1.30

use num_derive::FromPrimitive; // 0.2.4 (the derive)
use num_traits::FromPrimitive; // 0.2.6 (the trait)

Before Rust 1.30

#[macro_use]
extern crate num_derive; // 0.2.4
extern crate num_traits; // 0.2.6

use num_traits::FromPrimitive;

Usage

#[derive(Debug, FromPrimitive)]
pub enum MyEnum {
    Var1 = 1,
    Var2,
}

fn main() {
    println!("{:?}", MyEnum::from_u8(2));
}

Each project has their own crate containing their own derive macros. A small sample:

  • Num (e.g. FromPrimitive) => num_derive
  • Serde (e.g. Serialize, Deserialize) => serde_derive
  • Diesel (e.g. Insertable, Queryable) => diesel (it's actually the same as the regular crate!)

Some crates re-export their derive macros. For example, you can use the derive feature of Serde and then import it from the serde crate directly:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
use serde::{Serialize, Deserialize}; // imports both the trait and the derive macro

FromPrimitive was actually part of the standard library before Rust 1.0. It wasn't useful enough to continue existing in the standard library, so it was moved to the external num crate. Some very old references might not have been updated for this change.

For more information about converting C-like enums to and from integers, see:

Lukas Kalbertodt
  • 79,749
  • 26
  • 255
  • 305
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 1
    i'm using diesel, why isn't "derive" included with it? – jerry Mar 06 '18 at 02:52
  • @jerry Your question doesn't make any sense to me. `derive` is a special syntax understood by the compiler, no crate "includes" it. Crates define their own *derive macros* that are unique to each. – Shepmaster Mar 06 '18 at 02:56
  • 7
    Thanks for mentioning `features = ["derive"]`. It saved my time – IC_ Jul 08 '19 at 04:16