"no rules expected the token" when using macro to implement methods [closed] - rust

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 months ago.
Improve this question
I previously used C/C++ and recently started using Rust. I'm experiencing difficulties on writing simple macro_rules! to automatically implement some helper methods.
Originally, I had Scanner struct, which scans data from stdio and converts them into a given type.
struct Scanner {
buffer: Vec<String>
}
impl Scanner {
fn next<T: std::str::FromStr>(&mut self) -> T { /* tldr */ }
}
After that, I tried to implement a helper macro to implement two methods which return T and Vec<T> respectively.
// It doesn't work 😢
macro_rules! scanner_shortcut {
($scan_type:ident, $single_scan_ident:ident, &multi_scan_ident:ident) => {
impl Scanner {
fn $single_scan_ident(&mut self) -> $scan_type {
self.next()
}
fn $multi_scan_ident(&mut self, n: usize) -> Vec<$scan_type> {
(0..n).map(|_| self.next()).collect()
}
}
};
}
scanner_shortcut!(i32, scan_i32, scan_i32s);
scanner_shortcut!(i64, scan_i64, scan_i64s);
However, I got the following error message: no rules expected this token in macro call
error: no rules expected the token `scan_i32s`
--> src/bin/playground.rs:36:34
|
23 | macro_rules! scanner_shortcut {
| ----------------------------- when calling this macro
...
36 | scanner_shortcut!(i32, scan_i32, scan_i32s);
| ^^^^^^^^^ no rules expected this token in macro call
error: no rules expected the token `scan_i64s`
--> src/bin/playground.rs:37:34
|
23 | macro_rules! scanner_shortcut {
| ----------------------------- when calling this macro
...
37 | scanner_shortcut!(i64, scan_i64, scan_i64s);
| ^^^^^^^^^ no rules expected this token in macro call
I struggled to get rid of this problem, and I found that when I remove &multi_scan_ident:ident and the corresponding method declaration, it works well!
// It works well...  🧐
macro_rules! scanner_shortcut {
($scan_type:ident, $single_scan_ident:ident) => {
impl Scanner {
fn $single_scan_ident(&mut self) -> $scan_type {
self.next()
}
}
};
}
scanner_shortcut!(i32, scan_i32);
scanner_shortcut!(i64, scan_i64);
I guess the first code has some syntactic problems with the macro definition because the second version works well, but I couldn't figure out the exact reason. What makes this difference?
Any help will be appreciated!

You have a syntax error:
&multi_scan_ident:ident
This should be:
$multi_scan_ident:ident

Related

Why do I get the error that I can't 'move out of shared reference' when implemented inside a Derive macro, but not when done directly? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 14 hours ago.
Improve this question
I have this class:
#[derive(MyDerive)]
pub struct Streamers {
#[pk]
pub login: String,
pub display_name: Option<String>,
pub watched: Option<bool>,
}
and in that derive I have a method that looks something like this (inside an impl block in a trait):
quote::quote! {
fn get_pk_value(&self) -> #pk_ty {
self.#pk_ident.clone()
}
}
the #pk_ident is just 'login' and #pk_ty 'String'
the macro should just expand to this:
fn get_pk_value(&self) -> String {
self.login.clone()
}
and it does, at least in my cargo expand output, so why does the build fail?
When I type that code just normally it works but the build fails with this message:
error[E0507]: cannot move out of self.login which is behind a shared
reference
move occurs because self.login has type String, which does not
implement the Copy trait
shouldn't the clone remove that problem?

How should doc comments be spread over multiple elements? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 months ago.
Improve this question
I need to document a piece of code that is 3-fold. I have an enum element, an associated constructor and a method that uses the enum to do work. Here is a minimal example:
use regex::{Error, Regex};
pub enum Element {
And {
lhs: Box<Element>,
rhs: Box<Element>,
},
Value {
regex: Regex,
},
}
impl Element {
pub fn new_and(lhs: Element, rhs: Element) -> Self {
Element::And {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
}
}
pub fn new_value(regex: &str) -> Result<Self, Error> {
let regex = Regex::new(regex)?;
Ok(Element::Value { regex })
}
pub fn is_match(&self, values: &Vec<String>) -> bool {
match self {
Element::And { lhs, rhs } => lhs.is_match(values) && rhs.is_match(values),
Element::Value { regex } => {
for value in values {
if regex.is_match(value) {
return true;
}
}
false
}
}
}
}
fn main() {}
There definitely needs to be a comment on new_value() to document the possible error. But where should I put information on how the actual element is evaluated?
Put this also in the comment of new_value() to have all in one place?
Put it in a comment for Element::Value and is_match() only says that elements are
evaluated as documented there?
Put all evaluation information for all enum values in the comment for is_match() and leave Element::Value empty?
Repeat the evaluation information in all 3 locations?
Disclaimer: A lot of this will come down to personal preference and taste, there's not really any hard and fast rules
That being said, I like to look at the standard library's documentation for inspiration.
Generally, if a function returns a Result, some explanation of when it returns an error is probably a good idea. For example: Returns an error if the regex fails to parse. You could also look at the docs for Regex::new to see what they say about it.
When documenting the behaviour of is_match, you should probably put the comment on is_match.
But I'd also suggest putting a more comprehensive comment (preferably with a usage example) either in the module (with //! at the top) or on pub enum Element. Examples are really underrated IMO, and even a simple one can really help a reader to understand the purpose of this type.
For example, the docs for String (https://doc.rust-lang.org/std/string/struct.String.html) have quite a lot of detail on various uses of String as doc comments on the String struct itself.

Lint violation not caught when using macro_rules imported from another crate

I'm implementing a crate that has the purpose of wrapping some user code and make sure it is called in a certain context. I can summarize my workspace this way:
A "user_code" crate:
This contains a single "user" function, which I would have no control over. Notice that it returns a u32.
pub fn addition(a: u32, b: u32) -> u32 {
a + b
}
A "wrapper" crate:
This contains a macro_rules. This macro creates some modules and a caller function, which will call the user code seen above. This is a highly simplified version. Notice that the return value of addition is ignored.
#[macro_export]
macro_rules! macro_wrapper {
() => {
pub mod my_user_code {
use wrapper::*;
use user_code::*;
pub mod addition {
use wrapper::*;
use super::*;
pub fn caller(a: u32, b: u32) {
addition(a, b);
}
}
}
};
}
An "example" crate:
Here I simply call the wrapper macro, in order to form the modules and functions I need and then use in the main function.
#![deny(unused_results)]
use wrapper::macro_wrapper;
macro_wrapper! {
}
fn main() {
my_user_code::addition::caller(2,3);
println!("Hello, world!");
}
This might seem like super strange code (it is) but it's a very simplified example of a legit project :)
My goal now is to make sure that this code doesn't compile because the return value of addition is not used - it was forgotten. The lint #![deny(unused_results)] seems to achieve exactly what I want.
However, this works only if, instead of use wrapper::macro_wrapper; I have the macro directly defined in the main.rs. In that case I get:
error: unused result of type `u32`
--> example\src\main.rs:14:21
|
14 | addition(a, b);
| ^^^^^^^^^^^^^^^
...
21 | / macro_wrapper! {
22 | |
23 | | }
| |_- in this macro invocation
|
note: the lint level is defined here
--> example\src\main.rs:1:9
|
1 | #![deny(unused_results)]
| ^^^^^^^^^^^^^^
= note: this error originates in the macro `macro_wrapper` (in Nightly builds, run with -Z macro-backtrace for more info)
If the macro is defined in its crate "wrapper", the code compiles and runs just fine without any error. This is not the result I expect.
What am I missing here? Thank you in advance for reading!
The unused_results lint doesn't get fired for macro expansions for external macros. This is by design, because this lint can be very noisy, and you can't control the expansion of external macros.
If you need that, your best bet is to mark your function as #[must_use], then #![deny(unused_must_use)]. Because the unused_must_use lint does get fired for external macros, it will work.
If you can't control the function definition, a neat trick you can use is to define a dummy function whom only job is to trigger the lint:
#[doc(hidden)]
#[must_use]
pub fn must_use<T>(v: T) -> T { v }
// In the macro...
pub fn caller(a: u32, b: u32) {
$crate::must_use(addition(a, b));
}

How to define different function names with a macro?

I've been tyring to define a different function for eacu unsigned type in Rust, and of course they have to have different names because Rust can't pick the right one by signature. So I'm trying to give them different names but I was unable to do so:
macro_rules! define_my_function {
($t:ty, $f_name:ident) => {
pub fn concat_idents!(my_function_, $ty)()(
stream: &mut T
) -> Result<$ty, ParseError> {
todo!()
}
}
}
define_my_function!(u8, name_for_u8);
Compiling playground v0.0.1 (/playground)
error: expected one of `(` or `<`, found `!`
--> src/lib.rs:3:29
|
3 | pub fn concat_idents!(my_function_, $ty)()(
| ^ expected one of `(` or `<`
...
11 | define_my_function!(u8, name_for_u8);
| ------------------------------------- in this macro invocation
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=9ccea3ddcc75bb2cfab14c52df7bc24f
It looks like this is impossible in Rust. What can I do then? Also I don't want to use concat_idents as it's nightly only
You can use the paste crate, that internally uses a procedural macro to create new identifiers:
macro_rules! define_my_function {
($t:ty) => {
::paste::paste! {
pub fn [<my_function_ $t>]() {
println!(stringify!($t));
}
}
}
}
define_my_function!(u8);
define_my_function!(u16);
fn main() {
my_function_u8();
my_function_u16();
}
Playground
Note that I had to slightly change the code you gave because it wasn't compiling.
From the documentation for std::concat_idents:
Also, as a general rule, macros are only allowed in item, statement or expression position. That means while you may use this macro for referring to existing variables, functions or modules etc, you cannot define a new one with it.
Unfortunately, it seems that at the time this is possible using a procedural macro, or by manually copy-pasting for each numeric type.

How to resolve expected `:`, found keyword `self`?

I'm learning to write iterators in Rust but am hitting an "expected colon" issue where I would not expect a colon to even make sense. Maybe it has to do with lifetimes? References? I tried making a regular function that returns the same data in the same way and it worked (or at least got past this error message) so it appears to be special to the Iterator trait... but I can't work out why.
struct LogEntry;
pub struct LogIter<'a> {
index0: bool,
first: LogEntry,
iter: ::std::slice::Iter<'a, LogEntry>,
}
impl<'a> Iterator for LogIter<'a> {
type Item = &'a LogEntry;
fn next(&mut self) -> Option<Self::Item> {
self.index0 = false;
match self.index0 {
true => Some(&'a self.first),
false => self.iter.next(),
}
}
}
It is meant to return first and then iterate normally but I cannot figure out why or how I could possibly fit a colon in here.
error: expected `:`, found keyword `self`
--> src/lib.rs:14:30
|
14 | true => Some(&'a self.first),
| ^^^^ expected `:`
Your question is solved by pointing out that &'a foo isn't a valid expression. It doesn't make sense to specify a lifetime when taking a reference as the compiler will automatically ensure the correct lifetimes.
You want to use Some(&self.first).
Your problem is addressed by How do I write an iterator that returns references to itself?.

Resources