Removing last will break my library.
#[macro_export]
macro_rules! list {
() => {
None
};
[ $x:expr, $( $y:expr ),* ] => {
{
let mut first = cons($x, &None);
let mut last = &mut first;
$(
let yet_another = cons($y, &None);
if let Some(ref mut last_inner) = last {
let last_mut = Rc::get_mut(last_inner).unwrap();
last_mut.cdr = yet_another;
last = &mut last_mut.cdr;
}
)*
first
}
}
}
This macro works as I expected because it can pass these tests.
#[test]
fn dolist() {
let mut v = vec![];
dolist!((i &cons(10, &list![20, 30, 40])) {
v.push(i.car);
});
assert_eq!(v, vec![10, 20, 30, 40]);
}
#[test]
fn turn_list_to_vec() {
assert_eq!(list_to_vec(&list![1, 2, 3]), vec![1, 2, 3]);
}
#[test]
fn count_elements() {
assert_eq!(list_len(&list![10, 20, 30]), 3);
}
However I got the warning “value assigned to last is never read.”
How can I avoid this warning?
P.S. Full code
I’m not sure if the rules are different with macros, I’ve never written one but this lint is generally caused because you set a var to a value and then overwrite that value before you use it. e.g.
let mut a = 1; a = 2; println!(“{}”, a);
This will throw the same warning because 1 is never used, this could’ve just been:
let a = 2; println!(“{}”, a);
So first I’d double check that I NEED last at all. Maybe try:
cargo clippy
See if it can tell you how to fix it.
If that doesn’t work, it’s sometimes necessary to skip certain lints. E.g. if you make a library, most of the code will be flagged as dead code because it isn’t used and you can use an #[allow(dead_code)] to stop the linter warning. You might be able to use #[allow(this_linting_rule)].
Hope something here helps.
Clippy didn’t tell anything about the macro.
warning: dereferencing a tuple pattern where every element takes a reference --> src/lib.rs:13:9 | 13 | &Some(ref cons_rc) => { | ^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference = note: `#[warn(clippy::needless_borrowed_reference)]` on by default help: try removing the `&` and `ref` parts | 13 - &Some(ref cons_rc) => { 13 + Some(cons_rc) => { |
To put #[allow(this_linting_rule)] like this:
[ $x:expr, $( $y:expr ),* ] => { #[allow(unused_assignments)] {
I got error[E0658]: attributes on expressions are experimental.
To put it like this:
#[macro_export] #[allow(unused_assignments)] macro_rules! list { () => { None
It doesn’t work.
I would expect the following to work
#[allow(unused)] let mut last = &mut first;
It doesn’t work, at least, on rustc 1.75.
I misunderstood the reason the error was showing up. It seems like using a closure fixes it though.
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=247730dfc1fbeeb8e2263ea3b95d6c0a
#[macro_export] macro_rules! list { () => { None }; [ $x:expr, $( $y:expr ),* ] => {{ #[allow(unused_assignments)] let closure = move || { let mut first = cons($x, &None); let mut last = &mut first; $( let yet_another = cons($y, &None); if let Some(ref mut last_inner) = last { let last_mut = Rc::get_mut(last_inner).unwrap(); last_mut.cdr = yet_another; last = &mut last_mut.cdr; } )* first }; closure() }} }
Thank you. This works!