What are the use cases of raw identifiers besides new keywords? - rust

As in Rust 2018, we now have raw identifiers:
This feature is useful for a few reasons, but the primary motivation was inter-edition situations. For example, try is not a keyword in the 2015 edition, but is in the 2018 edition. So if you have a library that is written in Rust 2015 and has a try function, to call it in Rust 2018, you'll need to use the raw identifier.
Are there any other advantages than stated above? Are there plans to make keywords contextual, e.g. you can use type as identifier for variables? Why I should use a cryptic syntax like r#type instead of ty or something else?

Why I should use a cryptic syntax like r#type instead of ty or something else?
Sometimes the names of fields are used outside of your Rust program. For example, when serializing data with Serde, the field name is used in the output (e.g. JSON). So if you need JSON output with this:
"type": 27,
... then raw identifiers can help you:
#[derive(Serialize)]
struct Foo {
r#type: u32,
}
On the other hand... Serde already has a way to achieve what you want: the #[serde(rename = "name")] attribute. Reserved Rust keywords are one of the reasons why this attribute was introduced.
#[derive(Serialize)]
struct Foo {
#[serde(rename = "type")]
ty: u32,
}
Similarly, the Debug output also uses the field name in its output. So if you want the output Foo { type: 27 }, you can use raw identifiers:
#[derive(Debug)]
struct Foo {
r#type: u32,
}
On the other hand... if the exact Debug output is that important to you, you can simply implement it yourself:
impl fmt::Debug for Foo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Foo")
.field("type", &self.ty)
.finish()
}
}
So in practice, I don't see why one would use raw identifier for this purpose, since you have to use the strange r# syntax everywhere you use that name. It's probably easier to just fix this particular problem in another way.
So, as far as I see it, the "using API from another edition" is the only real use case for raw identifiers. Having such a syntax "just for the case" is a nice thing, though.

Ineed with raw_identifiers you can use type and other keywords as a variable/struct/etc. identifiers:
#![feature(rust_2018_preview)]
#![feature(raw_identifiers)]
struct r#let {} // just warnings: struct is never used: `let` and type `let` should have a camel case name such as `Let`
fn main() {
let r#type = 0; // just warning: unused variable: `type`
}
It doesn't work with every keyword, though:
let r#super = 0; // error: `r#super` is not currently supported.

Related

How to write a wrapper enum for C error codes?

I am writing a Rust wrapper for a C API. It contains a function that may fail, in which case it returns an error code encoded as an int. Let's call these SOME_ERROR and OTHER_ERROR, and they will have the values 1 and 2, respectively. I want to write an enum wrapping these error codes, as follows:
// Declared in a seperate C header
const SOME_ERROR: c_int = 1;
const OTHER_ERROR: c_int = 2;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
enum ErrorCodeWrapper {
SomeError = SOME_ERROR,
OtherError = OTHER_ERROR,
}
Here comes my first question. It does not seem to be possible to specify std::os::raw::c_int as the underlying type of an enum. But I do feel like it should be, as int isn't required to be 32 bits wide. Is there any way to achieve this?
I'd then like some methods to convert to and from a raw error code:
use std::os::raw::c_int;
impl ErrorCodeWrapper {
fn from_raw(raw: c_int) -> Option<Self> {
match raw {
SOME_ERROR => Some(Self::SomeError),
OTHER_ERROR => Some(Self::OtherError),
_ => None
}
}
unsafe fn from_raw_unchecked(raw: c_int) -> Self {
*(&raw as *const _ as *const Self)
}
fn as_raw(self) -> c_int {
unsafe { *(&self as *const _ as *const c_int) }
}
}
The only way I could find to "bit-cast" c_int to and from ErrorCodeWrapper is to do it C-style, by casting a pointer and then dereferencing it. This should work as ErrorCodeWrapper and int have the same size and alignment, and the value of every ErrorCodeWrapper variant maps to its corresponding error code. However, this solution is a bit to hackery for my taste; is there a more idiomatic one, like C++'s std::bit_cast?
Furthermore, is it possible to replace the match statement in ErrorCodeWrapper::from_raw with a simple validity check, for simpler code in the case of more variants?
The last bit of code, the necessary error implementations:
use std::{fmt::Display, error::Error};
impl Display for ErrorCodeWrapper {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", match self {
Self::SomeError => "some error",
Self::OtherError => "some other error",
})
}
}
impl Error for ErrorCodeWrapper {}
Now let's imagine a second wrapper, SuperErrorCodeWrapper, that includes some or all of the variants of ErrorCodeWrapper, with the same description and everything. That would mean that either:
One could "factor out" the common variants of ErrorCodeWrapper and SuperErrorCodeWrapper into a separate enum. ErrorCodeWrapper and SuperErrorCodeWrapper would then have a variant containing this enum. However I am not really fond of this kind of nesting, which would seem arbitrary when focusing on one particular error.
Duplicating the common variants across both enums.
The latter would add a lot to the existing boilerplate. Could a macro be a viable option to handle this?
Is there a library that could handle all this for me?
Here comes my first question. It does not seem to be possible to specify std::os::raw::c_int as the underlying type of an enum. But I do feel like it should be, as int isn't required to be 32 bits wide. Is there any way to achieve this?
No. There was an RFC in 2016 (I can't even access the RFC text. it seems it was removed), but it was closed:
We discussed in the #rust-lang/lang meeting and decided that while the RFC is well-motivated, it doesn't sufficiently address the various implementation complexities that must be overcome nor the interaction with hygiene. It would make sense to extend the attribute system to support more general paths before considering this RFC (but that is a non-trivial undertaking).
The best you can do is to use #[cfg_attr] with all configurations. c_int is defined here as, and all current options are
#[cfg_attr(any(target_arch = "avr", target_arch = "msp430"), repr(i16))]
#[cfg_attr(not(any(target_arch = "avr", target_arch = "msp430")), repr(i32))]
enum ErrorCodeWrapper { ... }
is there a more idiomatic one, like C++'s std::bit_cast?
Yes; std::mem::transmute().
One could "factor out" the common variants of ErrorCodeWrapper and SuperErrorCodeWrapper into a separate enum. ErrorCodeWrapper and SuperErrorCodeWrapper would then have a variant containing this enum.
If you do that, you lose the ability to transmute() (or pointer cast, it doesn't matter), as they'll be no longer layout compatible with int.
Could a macro be a viable option to handle this?
Probably yes.
Is there a library that could handle all this for me?
I don't know all library that handles all of this (although it is possible that one exists), but there is thiserror (and friends) for the Error and Display implementations, and strum::FromRepr that can help you with from_raw().

Propagate different errors when the function output is fixed by a macro [duplicate]

I want to learn how to properly deal with errors in Rust. I have read the book and this example; now I would like to know how I should deal with errors in this function:
fn get_synch_point(&self) -> Result<pv::synch::MeasPeriods, reqwest::Error> {
let url = self.root.join("/term/pv/synch"); // self.root is url::Url
let url = match url {
Ok(url) => url,
// ** this err here is url::ParseError and can be converted to Error::Kind https://docs.rs/reqwest/0.8.3/src/reqwest/error.rs.html#54-57 **//
Err(err) => {
return Err(Error {
kind: ::std::convert::From::from(err),
url: url.ok(),
})
}
};
Ok(reqwest::get(url)?.json()?) //this return reqwest::Error or convert to pv::sych::MeasPeriods automaticly
}
This code is improper; it causes a compilation error:
error[E0451]: field `kind` of struct `reqwest::Error` is private
--> src/main.rs:34:42
|
34 | Err(err) => return Err(Error{kind: ::std::convert::From::from(err), url: url.ok()})
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `kind` is private
error[E0451]: field `url` of struct `reqwest::Error` is private
--> src/main.rs:34:81
|
34 | Err(err) => return Err(Error{kind: ::std::convert::From::from(err), url: url.ok()})
| ^^^^^^^^^^^^^ field `url` is private
What is a proper pattern to deal with that case? For me, reqwest::Error in this case is a good solution so I would like to avoid defining my own error type:
enum MyError {
Request(reqwest::Error),
Url(url::ParseError) // this already a part of request::Error::Kind!!!
}
Update 2020
The rust programming language is evolving quickly so a new answer can be added! I really liked custom_error but now I think thiserror will be my loved one!
use thiserror::Error;
#[derive(Error, Debug)]
pub enum DataStoreError {
#[error("data store disconnected")]
Disconnect(#[from] io::Error),
#[error("the data for key `{0}` is not available")]
Redaction(String),
#[error("invalid header (expected {expected:?}, found {found:?})")]
InvalidHeader {
expected: String,
found: String,
},
#[error("unknown data store error")]
Unknown,
}
This allow change io::Error to DataStoreError::Disconnect with question mark ?. Go here for details
useful links:
great blog about using thiserror in combine with anyhow
Other interesting crates:
anyhow - Flexible concrete Error type built on std::error::Error
snafu - Situation Normal: All Fouled Up - SNAFU is a library to easily assign underlying errors into domain-specific errors while adding context. (similar to thiserror)
custom_error - This crate contains a macro that should make it easier to define custom errors without having to write a lot of boilerplate code.
for panics:
proc-macro-error - This crate aims to make error reporting in proc-macros simple and easy to use.
human-panic - Panic messages for humans. Handles panics by calling std::panic::set_hook to make errors nice for humans.
Unfortunately, in your case you cannot create a reqwest::Error from other error types, if the reqwest library does not provide a way to do so (and it likely doesn't). To solve this problem, which is very common, especially in applications which use multiple libraries, the proper solution would be one of the following:
Declare your own custom enum with all errors your application works with (or one subsystem of your application; granularity highly depends on the project), and declare From conversions from all errors you work with to this enum type.
As an extension of this approach, you can use error-chain (or quick-error, on which error-chain is basically based) to generate such custom types and conversions in a semi-automatic way.
Use a special, generic error type. There are basically two of them:
a. Box<Error> where Error is defined in the standard library.
b. Use the Error type defined in the failure crate.
Then the question mark operator will be able to convert any compatible error to one of these types because of various Into and From trait implementations.
Note that the failure crate is intended to be the way to define errors promoted in the Rust community. Not only does it provide a common error type and trait (which fixes various issues with the std::error::Error trait; see for example here), it also has facilities to define your own error types (for example, with failure_derive), and for tracking error context, causes and generating backtrace. Additionally, it tries to be as compatible with the existing error handling approaches as possible, therefore it can be used to integrate with libraries which use other, older approaches (std::error::Error, error-chain, quick-error) quite easily. So I strongly suggest you to consider using this crate first, before other options.
I have already started using failure in my application projects, and I just can't express how much easier and nicer error handling has become. My approach is as follows:
Define the Result type:
type Result<T> = std::result::Result<T, failure::Error>;
Use Result<Something> everywhere where an error can be returned, using the question mark operator (?) to convert between errors and functions like err_msg or format_err! or bail! to create my own error messages.
I have yet to write a library using failure, but I imagine that for libraries it would be important to create more specific errors declared as an enum, which can be done with the failure_derive crate. For applications, though, the failure::Error type is more than enough.
In that case, reusing the underlying error type is not possible because you cannot construct its hidden fields. And even when it is possible, I would advise against it, in order to make your code more flexible and future-proof.
Defining custom error types can involve writing a lot of boilerplate, but fortunately several libraries exist to alleviate this pain. failure, error-chain and quick-error were already mentioned above, but I would like to point you to a crate I wrote that involves even less boilerplate than the others : custom_error. With it, you can write:
#[macro_use] extern crate custom_error;
custom_error!{ MyError
Request{source: reqwest::Error} = "request error",
Url{source: url::ParseError} = "invalid url"
}
As already stated by
Vladimir Matveev, the failure crate should be your starting point. Here is my solution:
use std::io;
use std::result;
use failure::{Backtrace, Fail};
/// This is a new error type manged by Oxide library.
/// The custom derive for Fail derives an impl of both Fail and Display.
#[derive(Debug, Fail)]
pub enum OxideError {
#[fail(display = "{}", message)]
GeneralError { message: String },
#[fail(display = "{}", message)]
IoError {
message: String,
backtrace: Backtrace,
#[cause]
cause: io::Error,
},
}
/// Create general error
pub fn general(fault: &str) -> OxideError {
OxideError::GeneralError {
message: String::from(fault),
}
}
/// Create I/O error with cause and backtrace
pub fn io(fault: &str, error: io::Error) -> OxideError {
OxideError::IoError {
message: String::from(fault),
backtrace: Backtrace::new(),
cause: error,
}
}
This error enumeration is extendible which allows it to accommodate future modifications that might be made to the program.
It seems the anyhow crate is good excepts for not supporting Box<dyn StdError>.
Most error types implemented Display trait, so use this magic.
Customize an error
Implement From trait from all object that implements Display
pub struct MyError {
pub code: i32,
pub message: String,
}
impl<E: Display> From<E> for MyError {
fn from(value: E) -> Self {
MyError {
code: 0,
message: value.to_string(),
}
}
}
async fn hello() -> std::result::Result<(), &'static str> {
return Err("Hello world");
}
async fn test() -> std::result::Result<(), MyError> {
// &str
hello().await?;
// std::io::Error
std::fs::read("DD")?;
// serde_json::Error
let data = serde_json::from_str("[1,2,3]")?;
Ok(())
}

How can I extract a type from a procedural macro attribute using darling?

I need to be able to extract the type DieselHandler, ideally in a way that allows for repeatable data_loader attributes for transforming against multiple types.
#[derive(Loadable)]
#[data_loader(handler = DieselHandler<FooLoader>)]
If I use handler: syn::Type there is the error:
the trait bound syn::Type: FromMeta is not satisfied
the trait FromMeta is not implemented for syn::Type
How can I pass in a type here and maybe even check the wrapper structure?
#[derive(Debug, FromDeriveInput)]
#[darling(attributes(data_loader))]
struct LoadByArgs {
#[darling(default)]
internal: bool,
handler: ????,
}
#[proc_macro_derive(Loadable, attributes(data_loader))]
pub fn load_by(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let LoadByArgs {
internal, handler
} = FromDeriveInput::from_derive_input(&input).expect("can't parse attribute");
let expanded = quote! {
...
};
proc_macro::TokenStream::from(expanded)
}
darling requires the quotation marks when writing #[attr(foo = "bar")] because syn doesn't consider the quotation-free form to be a valid Meta, and the Meta is the basis of darling's entire API.
That's consistent with serde, which I still view as the closest thing to a standard for proc-macro APIs in Rust.
You can use darling::util::PathList if you want to write something like #[data_loader(DieselHandler)]. Technically type parameters are part of a path, so DieselHandler<FooLoader> should work on paper.

Is it possible to tell if a field is a certain type or implements a certain method in a procedural macro?

I created a procedural macro that implements a trait, but in order for this to work I need to get the raw bytes for every field. The problem is how to get the bytes of a field differs depending on the type of field.
Is there some way of testing if a function exists on a field and if it does not tries another function?
E.g. something like this:
if item.field::function_exist {
//do code
} else {
//do other code
}
Currently I am looking at creating another trait/member function that I just have to create for all primitives and create a procedural macro for larger fields such as structs. For example:
if item.field::as_bytes().exists {
(&self.#index).as_bytes()
} else {
let bytes = (&self.#index).to_bytes();
&bytes
}
With a string, it has a as_bytes member function, while i32 does not. This means I need extra code, when the member field of the struct is not a string. I might need a match rather than an if, but the if will suffice for the example.
Is it possible to tell if a field is a certain type or implements a certain method in a procedural macro?
No, it is not.
Macros operate on the abstract syntax tree (AST) of the Rust code. This means that you basically just get the characters that the user typed in.
If user code has something like type Foo = Option<Result<i32, MyError>>, and you process some code that uses Foo, the macro will not know that it's "really" an Option.
Even if it did know the type, knowing what methods are available would be even harder. Future crates can create traits which add methods to existing types. At the point in time that the procedural macro is running, these crates may not have even been compiled yet.
I am looking at creating another trait/member function that I just have to create for all primitives and create a procedural macro for larger fields such as structs.
This is the correct solution. If you look at any existing well-used procedural macro, that's exactly what it does. This allows the compiler to do what the compiler is intended to do.
This is also way better for maintainability — now these primitive implementations live in a standard Rust file, as opposed to embedded inside of a macro. Much easier to read and debug.
Your crate will have something like this:
// No real design put into this trait
trait ToBytes {
fn encode(&self, buf: &mut Vec<u8>);
}
impl ToBytes for str {
fn encode(&self, buf: &mut Vec<u8>) {
buf.extend(self.as_bytes())
}
}
// Other base implementations
And your procedural macro will implement this in the straightforward way:
#[derive(ToBytes)]
struct Foo {
a: A,
b: B,
}
becomes
impl ToBytes for Foo {
fn encode(&self, buf: &mut Vec<u8>) {
ToBytes::encode(&self.a, buf);
ToBytes::encode(&self.b, buf);
}
}
As a concrete example, Serde does the same thing, with multiple ways of serializing to and from binary data:
Bincode
CBOR
MessagePack
etc.

How to introspect all available methods and members of a Rust type?

Is there a way to print out a complete list of available members of a type or instance in Rust?
For example:
In Python, I can use print(dir(object))
In C, Clang has a Python API that can parse C code and introspect it.
Being unfamiliar with Rust tools, I'm interested to know if there is some way to do this, either at run-time or compile-time, either with compiler features (macros for example), or using external tools.
This question is intentionally broad because the exact method isn't important. It is common in any language to want to find all of a variable's methods/functions. Not knowing Rust well, I'm not limiting the question to specific methods for discovery.
The reason I don't define the exact method is that I assume IDEs will need this information, so there will need to be some kinds of introspection available to support this (eventually). For all I know, Rust has something similar.
I don't think this is a duplicate of Get fields of a struct type in a macro since this answer could include use of external tools (not necessarily macros).
Is there a way to print out a complete list of available members of a type or instance in Rust?
Currently, there is no such built-in API that you can get the fields at runtime. However you can retrieve fields by using two different ways.
Declarative Macros
Procedural Macros
Solution By Using Declarative Macro
macro_rules! generate_struct {
($name:ident {$($field_name:ident : $field_type:ty),+}) => {
struct $name { $($field_name: $field_type),+ }
impl $name {
fn introspect() {
$(
let field_name = stringify!($field_name);
let field_type = stringify!($field_type);
println!("Field Name: {:?} , Field Type: {:?}",field_name,field_type);
)*
}
}
};
}
generate_struct! { MyStruct { num: i32, s: String } }
fn main() {
MyStruct::introspect();
}
This will give you the output:
Field Name: "num" , Field Type: "i32"
Field Name: "s" , Field Type: "String"
Playground
Solution Using Procedural Macro
Since procedural macros are more complicated from the declarative macros, you better to read some references(ref1, ref2, ref3) before starting.
We are going to write a custom derive which is named "Instrospect". To create this custom derive, we need to parse our struct as a TokenStream with the help of syn crate.
#[proc_macro_derive(Introspect)]
pub fn derive_introspect(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemStruct);
// ...
}
Since our input can be parsed as ItemStruct and ItemStruct has the fields() method in it, we can use this to get fields of our struct.
After we get these fields, we can parse them as named and we can print their field name and field type accordingly.
input
.fields
.iter()
.for_each(|field| match field.parse_named() {
Ok(field) => println!("{:?}", field),
Err(_) => println!("Field can not be parsed successfully"),
});
If you want to attach this behavior to your custom derive you can use the following with the help of the quote crate:
let name = &input.ident;
let output = quote! {
impl #name {
pub fn introspect(){
input
.fields
.iter()
.for_each(|field| match field.parse_named() {
Ok(field) => println!("{:?}", field),
Err(_) => println!("Field can not be parsed successfully"),
});
}
}
};
// Return output TokenStream so your custom derive behavior will be attached.
TokenStream::from(output)
Since the behaviour injected to your struct as introspect function, you can call it in your application like following:
#[derive(Introspect)]
struct MyStruct {
num: i32,
text: String
}
MyStruct::introspect();
Note: Since the example you are looking for similar to this question. This Proc Macro Answer and Declarative Macro Answer should give you insight as well
To expand on my comment, you can use rustdoc, the Rust documentation generator, to view almost everything you're asking for (at compile time). rustdoc will show:
Structs (including public members and their impl blocks)
Enums
Traits
Functions
Any documentation comments written by the crate author with /// or //!.
rustdoc also automatically links to the source of each file in the [src] link.
Here is an example of the output of rustdoc.
Standard Library
The standard library API reference is available here and is available for anything in the std namespace.
Crates
You can get documentation for any crate available on crates.io on docs.rs. This automatically generates documentation for each crate every time it is released on crates.io.
Your Project
You can generate documentation for your project with Cargo, like so:
cargo doc
This will also automatically generate documentation for your dependencies (but not the standard library).
I have written a very simple crate which uses procedural macro. It gives you access to members information plus some simple information about struct/enum you use. Information about methods can not be given because procedural macros simply can't get this information, and as far as I know, there are no any methods which may give such information.
I don't think there is anything that will do this out of the box.
It may be possible to write a compiler plugin which can do that by examining the AST.
If you need the field names inside your program then you probably need to use macros. Either wrap your struct definition in macro and pattern match to create some function to get their names, or use procedural macro to derive structs for traits with such functions.
See examples in syn for derived traits. In particular, see syn::Data::Struct which has fields.
According to question of #AlexandreMahdhaoui, I would say: at least on latest Rust versions the proc_macro from accepted answer will not work, because you will need to pass tokens into quote! using "#". So you could try smth like next:
use proc_macro::{TokenStream};
use quote::{quote, ToTokens};
use syn::{parse_macro_input, ItemStruct};
#[proc_macro_derive(Introspect)]
pub fn derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemStruct);
let ident = input.ident;
let field_data = input.fields.iter().map(|f| {
let field_type = f.ty.clone();
format!(
"Name={}, Type={}",
f.ident.clone().unwrap().to_string(),
quote!(#field_type).to_string()
)
}).collect::<Vec<_>>();
let output = quote! {
impl #ident {
pub fn introspect() {
println!("{:#?}", vec![#(#field_data),*]);
}
}
};
TokenStream::from(output)
}
#[derive(Introspect)]
struct Test {
size: u8,
test_field: u8,
}
fn main() {
Test::introspect();
}
Regarding methods, defined in impl I didn't find any info in output, so not sure if it possible. Probably somebody could share in comments ?
I use something like this:
println!("{:?}", variable); // struct, enum whatever
If it's a large type, use the # version:
println!("{:#?}", variable); // struct, enum whatever

Resources