How to print the contents of a syn::Expr with println? - rust

I am trying to output the contents of a syn::Expr to the console, but get the following error:
error[E0599]: no method named `to_string` found for type `&syn::Expr` in the current scope
--> derive/src/lib.rs:165:40
|
165 | println!("Expression: {:#?}", expr.to_string());
| ^^^^^^^^^
|
= note: the method `to_string` exists but the following trait bounds were not satisfied:
`syn::Expr : std::string::ToString`
`&syn::Expr : std::string::ToString`
`syn::Expr : std::string::ToString`
It is not clear to me what "trait bounds" are or how to satisfy them. Are there any easy ways to output the contents of this variable?

syn::Expr is documented as implementing the Debug trait, so you use the Debug formatter:
extern crate syn; // 0.15.4
fn example(expr: syn::Expr) {
println!("{:#?}", expr);
}
However, all Debug implementations in syn are guarded by the Cargo feature extra-traits. So in order to use those Debug impls, you have to specifically enable that feature in your Cargo.toml:
[dependencies]
syn = { version = "0.15", features = ["extra-traits"] }
You can read more about syn's optional Cargo features in their README.
See also:
How do I print variables in Rust and have it show everything about that variable, like Ruby's .inspect?
What is the difference between println's format styles?
Should I implement Display or ToString to render a type as a string?
Does println! borrow or own the variable?

Related

Clap options with derive macros fails to compile in rust clap 3.0.0-beta.5

I'm trying out the "Using Derive Macros" example on the index page for the latest beta version of clap:
// (Full example with detailed comments in examples/01d_quick_example.rs)
//
// This example demonstrates clap's full 'custom derive' style of creating arguments which is the
// simplest method of use, but sacrifices some flexibility.
use clap::{AppSettings, Parser};
/// This doc string acts as a help message when the user runs '--help'
/// as do all doc strings on fields
#[derive(Parser)]
#[clap(version = "1.0", author = "Kevin K. <kbknapp#gmail.com>")]
struct Opts {
/// Sets a custom config file. Could have been an Option<T> with no default too
#[clap(short, long, default_value = "default.conf")]
config: String,
/// Some input. Because this isn't an Option<T> it's required to be used
input: String,
/// A level of verbosity, and can be used multiple times
#[clap(short, long, parse(from_occurrences))]
verbose: i32,
#[clap(subcommand)]
subcmd: SubCommand,
}
...
Unfortunately it fails to compile:
$ cargo build
Compiling ex v1.0.0-SNAPSHOT (/home/hwalters/git/home/ex)
error: cannot find derive macro `Parser` in this scope
--> src/main.rs:5:10
|
5 | #[derive(Parser)]
| ^^^^^^
|
note: `Parser` is imported here, but it is only a trait, without a derive macro
--> src/main.rs:1:25
|
1 | use clap::{AppSettings, Parser};
| ^^^^^^
error: cannot find attribute `clap` in this scope
--> src/main.rs:6:3
|
6 | #[clap(version = "1.0", author = "Kevin K. <kbknapp#gmail.com>")]
| ^^^^
|
= note: `clap` is in scope, but it is a crate, not an attribute
...
I tried to find the full example file "examples/01d_quick_example.rs" in the tar file for this GitHub tag, but it does not seem exist there.
I appreciate this is a beta version, but is this functionality expected to work, or am I doing something wrong?
Thanks!
In clap, use features = [ "derive" ] in Cargo.toml to enable the ability to derive :)
update
#stein below makes a good point of expanding the answer:
To "use" means: in the [dependencies] section, specify clap with a
line similar to: clap = { version = "3.1.0", features = ["derive"]} – 
Stein Feb 19 at 13:00
Please +1 their comment :-).
This means, in your Cargo.toml
[dependencies]
# ...
clap = { version = "3", features = ["derive"]}

How to use two traits with enum_dispatch?

I've tried:
#[enum_dispatch(BarTrait, BazTrait)]
pub enum Foo {
VariantZero,
...
}
It seems to ignore any traits after the first, silently.
This causes errors, as in this case the compiler doesn't seem to believe that Foo implements BazTrait.
Update: #kmdreko's code works properly so long as BazTrait is in the same crate as Foo.
When BazTrait is in a different crate, which also uses enum_dispatch, BazTrait is ignored and causes two errors of the form:
error[E0599]: no method named `baz` found for enum `Foo` in the current scope
--> src/main.rs:53:9
|
45 | enum Foo {
| -------- method `baz` not found for this
...
53 | foo.baz();
| ^^^ method not found in `Foo`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `baz`, perhaps you need to implement it:
candidate #1: `mylib::BazTrait`
It is important to note that there is no error at either #[enum_dispatch(BarTrait, BazTrait)] or pub enum Foo {.
The #[enum_dispatch] attribute does not work across crates:
Unfortunately, procedural macros in Rust are limited in a few ways that will make what you're trying to achieve impossible - notably, they are run independently per-crate, so there's no way for information from one crate to affect an implementation in another.
From the author of enum_dispatch in an unrelated issue.

How do I access a Navigator or other web-based resources in web_sys?

Recently I read the documentation of Rust and now I decided to play around with the web_sys API. I'm trying to use the Navigator::do_not_track getter... well, to be more specific I would like to print the returning value. According to the documentation, that's the signature of the getter:
pub fn do_not_track(&self) -> String
If I understand this correctly, I should be able to use the format! macro:
format!("{}", Navigator::do_not_track);
I have correctly imported the Navigator API, without any doubt. The error is:
error[E0277]: `for<'r> fn(&'r web_sys::features::gen_Navigator::Navigator) -> std::string::String {web_sys::features::gen_Navigator::Navigator::do_not_track}` doesn't implement `std::fmt::Display`
--> src/lib.rs:19:19
|
19 | format!("{}", Navigator::do_not_track);
| ^^^^^^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r web_sys::features::gen_Navigator::Navigator) -> std::string::String {web_sys::features::gen_Navigator::Navigator::do_not_track}` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `for<'r> fn(&'r web_sys::features::gen_Navigator::Navigator) -> std::string::String {web_sys::features::gen_Navigator::Navigator::do_not_track}`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
= note: required by `std::fmt::Display::fmt`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
And if I try to use web_sys::navigator, I get
could not find "navigator" in "web_sys"
How do I access the web navigator API using web_sys?
Note that Navigator::do_not_track is a method, which means that a value of type Navigator needs to be retrieved first. One possible source of confusion was in not finding how to create it.
Most of the Web resources that you would find as global variables in a DOM-enabled JavaScript environment are available through the Window resource. You need to:
Ensure that the intended resource is active by enabling the corresponding Cargo feature:
web_sys = { version = "0.3", features = ["Navigator, Window"] }
Retrieve the global window via web_sys::window, checking that it is available.
You can finally retrieve the intended resource through one of the available getter methods (window.navigator()).
The code:
let window = web_sys::window().expect("Missing Window");
let navigator = window.navigator();
let do_not_track = navigator.do_not_track();
See also:
The wasm-bindgen guide, which also includes guidance on using web-sys.

Is there any straightforward way for Clap to display help when no command is provided?

I'm using the Clap crate for parsing command line parameters. I've defined a subcommand ls that should list files. Clap also defines a help subcommand that displays information about the application and its usage.
If no command is provided, nothing gets displayed at all, but I want the app to display help in that case.
I've tried this code, which looks pretty straightforward, but it doesn't work:
extern crate clap;
use clap::{App, SubCommand};
fn main() {
let mut app = App::new("myapp")
.version("0.0.1")
.about("My first CLI APP")
.subcommand(SubCommand::with_name("ls").about("List anything"));
let matches = app.get_matches();
if let Some(cmd) = matches.subcommand_name() {
match cmd {
"ls" => println!("List something here"),
_ => eprintln!("unknown command"),
}
} else {
app.print_long_help();
}
}
I get an error that app is used after move:
error[E0382]: use of moved value: `app`
--> src/main.rs:18:9
|
10 | let matches = app.get_matches();
| --- value moved here
...
18 | app.print_long_help();
| ^^^ value used here after move
|
= note: move occurs because `app` has type `clap::App<'_, '_>`, which does not implement the `Copy` trait
Reading through the documentation of Clap, I've found that the clap::ArgMatches that's returned in get_matches() has a method usage that returns the string for usage part, but, unfortunately, only this part and nothing else.
Use clap::AppSettings::ArgRequiredElseHelp:
App::new("myprog")
.setting(AppSettings::ArgRequiredElseHelp)
See also:
Method call on clap::App moving ownership more than once
You can also use Command::arg_required_else_help as a bool on the command itself.
Command::new("rule").arg_required_else_help(true)

Use of Rust alignment feature (issue 33626)

RFC 1358 suggested an alignment attribute #[repr(align="N")] and it was accepted. Rust issue 33626 incorporated the feature into the nightly version.
I'm unable to use this feature with rustc 1.19.0-nightly (777ee2079 2017-05-01). If I compile without the feature gate (#![feature(repr_align)]):
#[repr(align="16")]
struct Foo {
bar: u32,
}
I get the following error statement:
error: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
--> foo.rs:3:1
|
3 | / struct Foo {
4 | | bar: u32,
5 | | }
| |_^
|
= help: add #![feature(repr_align)] to the crate attributes to enable
When I compile with the feature gate, the error message says:
error[E0552]: unrecognized representation hint
--> foo.rs:3:8
|
3 | #[repr(align="16")]
| ^^^^^^^^^^
I also tried the version suggested by the first error message (even though it does not comply with the issue), but still without success. What is the correct way to use the alignment feature?
You can make that feature work when combined with
attribute literals (Playground):
#![feature(repr_align)]
#![feature(attr_literals)]
#[repr(align(16))]
struct Foo {
bar: u32,
}
This is known to work in the latest development version (PR #41673). Searching "repr align" in the Rust compiler's codebase,
all occurrences rely on attribute literals, so it seems likely that the documented form repr(align="N") is not yet supported.

Resources