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

  • 5C5C5C@programming.dev
    link
    fedilink
    arrow-up
    14
    ·
    8 months ago

    If you put an underscore as the first character in the variable name, that tells the compiler that the variable may go unused and you’re okay with that. E.g.

    let mut _last = &mut first;
    
  • sugar_in_your_tea@sh.itjust.works
    link
    fedilink
    arrow-up
    4
    ·
    edit-2
    8 months ago

    A hack would be to do a simple noop read, like:

    if last.is_some() {}
    first
    

    The problem seems to be the last last = last_mut.cdr;, since you don’t use it on the last iteration.

    I’d personally do that with a comment until you (or someone else) can fix it, perhaps with a linter instruction at some point. That noop code should be eliminated during the optimization step, so it shouldn’t hurt performance or anything.

    Edit: don’t do this, just prefix the variable with an underscore as someone else mentioned.

  • Solemarc@lemmy.world
    link
    fedilink
    arrow-up
    2
    ·
    8 months ago

    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.

    • veer66@lemmy.oneOP
      link
      fedilink
      English
      arrow-up
      2
      ·
      8 months ago

      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.