44

I forgot to specify the type of a parameter and the error message was as follows:

error: expected one of `:` or `@`, found `)`
 --> src/main.rs:2:12
  |
2 | fn func(arg)
  |            ^ expected one of `:` or `@` here

Which raises the question: what can you do with an @ symbol? I don't remember reading about using the @ symbol for anything. I also did some Googling and couldn't find anything. What does @ do?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Michael Dorst
  • 8,210
  • 11
  • 44
  • 71

2 Answers2

42

You can use the @ symbol to bind a pattern to a name. As the Rust Reference demonstrates:

let x = 1;

match x {
    e @ 1 ... 5 => println!("got a range element {}", e),
    _ => println!("anything"),
}

Assignments in Rust allow pattern expressions (provided they are complete) and argument lists are no exception. In the specific case of @, this isn't very useful because you can already name the matched parameter. However, for completeness, here is an example which compiles:

enum MyEnum {
    TheOnlyCase(u8),
}

fn my_fn(x @ MyEnum::TheOnlyCase(_): MyEnum) {}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Wesley Wiser
  • 9,491
  • 4
  • 50
  • 69
  • When I read [the docs](https://doc.rust-lang.org/1.8.0/book/patterns.html#bindings), I think it finally clicked for me – but would I be correct in saying that pattern binding with `@` is shorthand for guards? E.g., `e if 1 <= e && e <= 5`? Not saying the shorthand wouldn't be helpful / possibly make the source clearer (assuming the syntax is understood) – I just want to make sure I'm not missing a use case of `@` in the spirit of "what can you do with the `@` symbol". – Sean Allred May 17 '19 at 03:02
  • 2
    @SeanAllred That's certainly one way to look at it. In the examples I gave, you'd basically be correct. The only thing I'd mention is that patterns can be nested and `@` let's you bind different parts of a structure to various names: `a @ Some(p @ Point { x = 5, .. })` now `a` has type `Option` and `p` has type `Point`. – Wesley Wiser May 17 '19 at 15:37
0

The @ symbol allows you to reuse a variable holding a value that's used simultaneously in a match pattern.

For example:

enum Student {
    Junior{ id: u32}
}

let me = Student::Junior{ id: 10 };

match me {
    Student::Junior{ id: id_val @ 0..=10 } => println!("in range with id: {}", id_val),
    Student::Junior{ id: 11..=20 } => println!("in range 11->20"),
    Student::Junior{ id } => println!("outside range with id: {}", id)
}

In this example, by binding id to the id_val the match can be used in the println!(), otherwise this won't be possible as seen in the second match expression.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83