this post was submitted on 13 Mar 2024
11 points (100.0% liked)

Rust

5658 readers
32 users here now

Welcome to the Rust community! This is a place to discuss about the Rust programming language.

Wormhole

[email protected]

Credits

  • The icon is a modified version of the official rust logo (changing the colors to a gradient and black background)

founded 1 year ago
MODERATORS
 

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

you are viewing a single comment's thread
view the rest of the comments
[–] [email protected] 2 points 5 months ago (5 children)

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.

[–] [email protected] 2 points 5 months ago (4 children)

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.

[–] [email protected] 1 points 5 months ago (3 children)

I would expect the following to work

#[allow(unused)]
let mut last = &mut first;
[–] [email protected] 1 points 5 months ago (1 children)

It doesn't work, at least, on rustc 1.75.

[–] [email protected] 2 points 5 months ago* (last edited 5 months ago) (1 children)

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()
    }}
}
[–] [email protected] 2 points 5 months ago
  #[allow(unused_assignments)]

Thank you. This works!

load more comments (1 replies)
load more comments (1 replies)
load more comments (1 replies)