Minor confusion about `_` pattern in a function parameter

fn main(){
  let x = String::from("hello");
  fn meow(_:String){
      
  }
  let _:String = x; // no move
  // wo `let` it is an underscore expression though
  _ = x; // no move
//meow(x); // move
  x;
}

Why does the pattern throw the value away in a function call?

The reference was to an extent confusing for me (but I may have missed different behaviour on functions?):

Unlike identifier patterns, it does not copy, move or borrow the value it matches.

Also, according to the function reference, the function meow would translate to:

// argument_0 is the actual first argument passed from the caller
let _ = argument_0;
()

The let _ = x is a pattern, or more specifically an identifier pattern. It's not used, so as the reference specifies, it's not moved, copied, or borrowed. It's usually not used alone like this.

The _ in fn meow(_: String) is an identifier (from the function reference). It would be very misleading for a user of a library to see a function signature with a parameter that's supposed to move a value which actually doesn't move it.

You could compare that to:

let s = "a".to_string();
let _t = s;
println!("{s}"); // <--- error

Because the argument is always moved into the function call, and only inside the function it is bound to some pattern.

As you've noticed yourself, any pattern in function arguments list can be treated as a sequence of two actions: first binding the argument to a simple identifier - this is the moment when the argument is moved; then rebinding this value from that temporary identifier to the actual pattern. It's correct that the wildcard pattern doesn't consume the bound-to value - but it is bound to the argument already at this time, it's already inside the function.

1 Like

thanks, you are right; i'd expect that it's simply a wildcard pattern as it is in a let statement, but i will just remember this.