How can I find where a symbol used in `derive` is defined? - rust

I come from a Java background, in which finding a symbol definition location is straightforward: it's ether in the same package or it comes via the imports.
Here Deserialize is defined in the serde crate, yet the source file contains no references to serde crate:
#[derive(Deserialize)]
struct Args {
arg_spec: Vec<String>,
flag_short: bool,
flag_porcelain: bool,
flag_branch: bool,
flag_z: bool,
flag_ignored: bool,
flag_untracked_files: Option<String>,
flag_ignore_submodules: Option<String>,
flag_git_dir: Option<String>,
flag_repeat: bool,
flag_list_submodules: bool,
}
(source)

Notice the declaration:
#[macro_use]
extern crate serde_derive;
(source)
This brings all the macros defined in the serde_derive crate into scope. One of those is the Deserialize macro which helps implement the Deserialize trait.
This was the old way of doing things. In the 2018 edition, the preferred way is to import macros with the more familiar use statements.

Related

Strange struct definition from crate nix

I just encountered this weird struct definition, it is in fcntl.rs from the crate nix.
pub struct OFlag: c_int {
/// Mask for the access mode of the file.
O_ACCMODE;
// other fields are omitted.
}
A normal struct in my perspective will be something like this:
struct Person{
name: String,
age: u8,
}
So, here are my doubts:
what is OFlag: c_int?
c_int is an type alias of i32. pub type c_int = i32;
Why don't its fields have any type annotation?
My surmise is that OFlag is of type c_int, and the fields are something similar to enum's fields.(compliant to the open syscall function signature int open(const char *pathname, int flags, mode_t mode) ) But this is just my guesswork, an explanation citing rust official doc would be appreciated.
The code you quoted is not valid Rust code on its own. It's code that gets passed to an internal macro of the nix crate called libc_bitflags!(). This macro takes the quoted code as input and transforms it into valid Rust code.
The libc_bitflags!() macro is a simple wrapper around the bitflags!() macro from the bitflags crate. The wrapper simplifies creating bitflags structs that take all their values from constants defined in the libc crate. For example this invocation
libc_bitflags!{
pub struct ProtFlags: libc::c_int {
PROT_NONE;
PROT_READ;
PROT_WRITE;
PROT_EXEC;
}
}
gets expanded to
bitflags!{
pub struct ProtFlags: libc::c_int {
const PROT_NONE = libc::PROT_NONE;
const PROT_READ = libc::PROT_READ;
const PROT_WRITE = libc::PROT_WRITE;
const PROT_EXEC = libc::PROT_EXEC;
}
}
which in turn will be expanded to Rust code by the bitflags!() macro. The libc::c_int type is used as the type of the bits field of the resulting struct. The constants inside will become associated constants of the resulting struct. See the documentation of the bitflags crate for further details.
If you look at the file you can see that the code inside the macro libc_bitflags!. The definition of the macro is here. There you can see that the macro ::bitflags::bitflags! is called and that libc_bitflags almost redirects the full input to bitflags. You can read more about that crate here.
Now to your questions:
OFlag will be after macro expansion a struct with a single attribute which is of type c_int:
pub struct OFlag {
bits: c_int,
}
The fields don't need a type because they won't exist anymore in the expanded code (after the macro was run). The bits are of the "type of the struct" so in your case c_int. The fields will be converted to associated constants:
impl OFlag {
pub const O_ACCMODE = Self { bits: libc::O_ACCMODE };
}
You can create an expansion of an example in the playground (Tools -> Expand macros)

Create struct that is usable with sqlx, has a datetime AND is serializable. Or how to enable serde?

I have a struct that contains a date and I use it with sqlx to retrieve data from my database. So something like:
use sqlx::types::chrono::{DateTime, Utc};
pub struct Account {
pub id: i32,
pub primary_email_id: i32,
pub created: DateTime<Utc>,
}
and
sqlx::query_as!(Account, "select * ...")
This works fine so far. But I also want Account to be serializable via serde. The obvious approach is:
#[derive(Serialize)]
pub struct Account {
...
This fails, because the Serialize trait is not implemented for DateTime<Utc>. I tried the same with PrimitiveDateTime from the time crate with the same result. In theory both should support serde as a feature.
I tried to explicitly add time or chrono as dependency, to enable serde as feature and use the type without the sqlx::types prefix. But in that case it fails because some sqlx traits are not implemented.
I assume that I somehow have to enable the serde feature for the classes brought in by sqlx, but I have no idea how to specify a feature for a feature!?
How to I tell sqlx to enable serde for the time/chrono types?
This depends on the time and chrono Cargo features of sqlx. So ensure the [dependencies] section of your Cargo.toml file includes these. As an example:
sqlx = { version = "0.6.0", features = [ "postgres", "runtime-tokio-native-tls", "offline", "time", "chrono" ] }
(This is essentially the comment of #Stargateur above. All credit to them.)

How can I fix cannot find derive macro `Deserialize` in this scope? [duplicate]

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?
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:
How do I match enum values with an integer?
How do I get the integer value of an enum?

How to write a custom derive macro?

I'm trying to write my own derive mode macro in Rust, and the documentation on it is somewhat lacking in examples.
I have a struct like:
#[derive(MyMacroHere)]
struct Example {
id: i64,
value: Option<String>,
}
I want my macro to generate a method à la
fn set_fields(&mut self, id: i64, value: Option<String>) {
// ...
}
What are the basic steps to use the TokenStream trait to achieve something like that?
Create a crate for your procedural macros:
cargo new my_derive --lib
Edit the Cargo.toml to make it a procedural macro crate:
[lib]
proc-macro = true
Implement your procedural macro:
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_derive(MyMacroHere)]
pub fn my_macro_here_derive(input: TokenStream) -> TokenStream {
// ...
}
Import the procedural macro and use it:
extern crate my_derive;
use my_derive::MyMacroHere;
#[derive(MyMacroHere)]
struct Example {
id: i64,
value: Option<String>,
}
The hard part is in implementation of the macro. Most people use the syn and quote crates to parse the incoming Rust code and then generate new code.
For example, syn's documentation starts with an example of a custom derive. You will parse the struct (or enum or union) and then handle the various ways of defining a struct (unit, tuple, named fields). You'll collect the information you need (type, maybe name), then you'll generate the appropriate code.
See also:
How to Write a Custom derive Macro
Documentation for proc_macro
Documentation for syn
Documentation for quote
Is it possible to add your own derivable traits, or are these fixed by the compiler?

How do I fix "cannot find derive macro in this scope"?

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?
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:
How do I match enum values with an integer?
How do I get the integer value of an enum?

Resources