Parameter Inversion in `matches!()`

What does this code output?

#[()]
pub enum  {
    ,
    
}

fn () {
    let  = ::;

    if !(::, ) {
        !("{fruit:?} is Apple");
    } else {
        !("{fruit:?} is Orange");
    }
}

Free fruit at the fruit store if you guessed Orange is Apple!

During development, I frequently ignore common compiler warnings like unused variables because they are usually leftovers from past versions of code that I clean up later. It bit me today because I accidentally inverted the order of parameters in the matches! macro, which matched Fruit::Apple to the catch-all variable fruit (unrelated to the local variable declared on line 10).

This can be seen with cargo-expand:

#![(prelude_import)]
#[]
use std::prelude::::*;
#[]
extern crate std;
pub enum  {
    ,
    ,
}
#[]
impl ::core::fmt:: for  {
    #[]
    fn (&, : &mut ::core::fmt::) -> ::core::fmt:: {
        ::core::fmt::::(
            ,
            match  {
                :: => "Apple",
                :: => "Orange",
            },
        )
    }
}
fn () {
    let  = ::;
    if match :: {
         => true,
        _ => false,
    } {
        {
            ::std::io::(!("{0:?} is Apple\n", ));
        };
    } else {
        {
            ::std::io::(!("{0:?} is Orange\n", ));
        };
    }
}

To be fair, the compiler does raise a warning, but it’s vague and as previously mentioned, easily glossed over:

warning: unused variable: `fruit`
  --> src/main.rs:11:31
   |
11 |     if matches!(Fruit::Apple, fruit) {
   |                               ^^^^^ help: if this is intentional, prefix it with an underscore: `_fruit`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: `testing` (bin "testing") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/testing`
Orange is Apple
src
fn main()
core::macros
macro_rules! matches

Returns whether the given expression matches the provided pattern.

The pattern syntax is exactly the same as found in a match arm. The optional if guard can be used to add additional checks that must be true for the matched value, otherwise this macro will return false.

When testing that a value matches a pattern, it’s generally preferable to use assert_matches as it will print the debug representation of the value if the assertion fails.

Examples

let foo = 'f';
assert!(matches!(foo, 'A'..='Z' | 'a'..='z'));

let bar = Some(4);
assert!(matches!(bar, Some(x) if x > 2));
core::fmt
pub struct Formatter<'a> {
    flags: u32,
    fill: char,
    align: Alignment,
    width: Option<usize>,
    precision: Option<usize>,
    /* … */
}

Configuration for formatting.

A Formatter represents various options related to formatting. Users do not construct Formatters directly; a mutable reference to one is passed to the fmt method of all formatting traits, like Debug and Display.

To interact with a Formatter, you’ll call various methods to change the various options related to formatting. For examples, please see the documentation of the methods defined on Formatter below.

core::fmt::Formatter
impl<'a> Formatter<'a>
pub fn write_str(&mut self, data: &str) -> Result

Writes some data to the underlying buffer contained within this formatter.

Examples

use std::fmt;

struct Foo;

impl fmt::Display for Foo {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("Foo")
        // This is equivalent to:
        // write!(formatter, "Foo")
    }
}

assert_eq!(format!("{Foo}"), "Foo");
assert_eq!(format!("{Foo:0>8}"), "Foo");
src
pub enum Fruit {
    Apple,
    Orange,
}
#[macro_use]

Valid forms are:

  • #[macro_use]
  • #[macro_use(name1, name2, …)]
#[inline]

Valid forms are:

  • #[inline]
  • #[inline(always|never)]
core::fmt
pub type Result = result::Result<(), Error>

The type returned by formatter methods.

Examples

use std::fmt;

#[derive(Debug)]
struct Triangle {
    a: f32,
    b: f32,
    c: f32
}

impl fmt::Display for Triangle {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}, {}, {})", self.a, self.b, self.c)
    }
}

let pythagorean_triple = Triangle { a: 3.0, b: 4.0, c: 5.0 };

assert_eq!(format!("{pythagorean_triple}"), "(3, 4, 5)");
core::fmt::macros
macro Debug

Derive macro generating an impl of the trait Debug.

#[prelude_import]

Valid forms are:

  • #[prelude_import]
src::Fruit
Apple = 0
std::prelude
mod rust_2021

The 2021 version of the prelude of The Rust Standard Library.

See the module-level documentation for more.

std::macros
macro_rules! println

Prints to the standard output, with a newline.

On all platforms, the newline is the LINE FEED character (\n/U+000A) alone (no additional CARRIAGE RETURN (\r/U+000D)).

This macro uses the same syntax as format, but writes to the standard output instead. See [std::fmt] for more information.

The println! macro will lock the standard output on each call. If you call println! within a hot loop, this behavior may be the bottleneck of the loop. To avoid this, lock stdout with io::stdout().lock:

use std::io::{stdout, Write};

let mut lock = stdout().lock();
writeln!(lock, "hello world").unwrap();

Use println! only for the primary output of your program. Use [eprintln] instead to print error and progress messages.

See the formatting documentation in std::fmt for details of the macro argument syntax.

Panics

Panics if writing to [io::stdout] fails.

Writing to non-blocking stdout can cause an error, which will lead this macro to panic.

Examples

println!(); // prints just a newline
println!("hello there!");
println!("format {} arguments", "some");
let local_variable = "some";
println!("format {local_variable} arguments");
self: &Fruit
core::macros::builtin
macro_rules! format_args

Constructs parameters for the other string-formatting macros.

This macro functions by taking a formatting string literal containing {} for each additional argument passed. format_args! prepares the additional parameters to ensure the output can be interpreted as a string and canonicalizes the arguments into a single type. Any value that implements the [Display] trait can be passed to format_args!, as can any [Debug] implementation be passed to a {:?} within the formatting string.

This macro produces a value of type [fmt::Arguments]. This value can be passed to the macros within std::fmt for performing useful redirection. All other formatting macros (format!, write, println!, etc) are proxied through this one. format_args!, unlike its derived macros, avoids heap allocations.

You can use the [fmt::Arguments] value that format_args! returns in Debug and Display contexts as seen below. The example also shows that Debug and Display format to the same thing: the interpolated format string in format_args!.

let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
assert_eq!("1 foo 2", display);
assert_eq!(display, debug);

See the formatting documentation in std::fmt for details of the macro argument syntax, and further information.

Examples

use std::fmt;

let s = fmt::format(format_args!("hello {}", "world"));
assert_eq!(s, format!("hello {}", "world"));

Lifetime limitation

Except when no formatting arguments are used, the produced fmt::Arguments value borrows temporary values, which means it can only be used within the same expression and cannot be stored for later use. This is a known limitation, see #92698.

#[feature]

Valid forms are:

  • #[feature(name1, name2, …)]
f: &mut Formatter<'_>
core::fmt
pub trait Debug

? formatting.

Debug should format the output in a programmer-facing, debugging context.

Generally speaking, you should just derive a Debug implementation.

When used with the alternate format specifier #?, the output is pretty-printed.

For more information on formatters, see the module-level documentation.

This trait can be used with #[derive] if all fields implement Debug. When derived for structs, it will use the name of the struct, then {, then a comma-separated list of each field’s name and Debug value, then }. For enums, it will use the name of the variant and, if applicable, (, then the Debug values of the fields, then ).

Stability

Derived Debug formats are not stable, and so may change with future Rust versions. Additionally, Debug implementations of types provided by the standard library (std, core, alloc, etc.) are not stable, and may also change with future Rust versions.

Examples

Deriving an implementation:

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

let origin = Point { x: 0, y: 0 };

assert_eq!(
    format!("The origin is: {origin:?}"),
    "The origin is: Point { x: 0, y: 0 }",
);

Manually implementing:

use std::fmt;

struct Point {
    x: i32,
    y: i32,
}

impl fmt::Debug for Point {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Point")
         .field("x", &self.x)
         .field("y", &self.y)
         .finish()
    }
}

let origin = Point { x: 0, y: 0 };

assert_eq!(
    format!("The origin is: {origin:?}"),
    "The origin is: Point { x: 0, y: 0 }",
);

There are a number of helper methods on the Formatter struct to help you with manual implementations, such as [debug_struct].

Types that do not wish to use the standard suite of debug representations provided by the Formatter trait (debug_struct, debug_tuple, debug_list, debug_set, debug_map) can do something totally custom by manually writing an arbitrary representation to the Formatter.

impl fmt::Debug for Point {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Point [{} {}]", self.x, self.y)
    }
}

Debug implementations using either derive or the debug builder API on Formatter support pretty-printing using the alternate flag: {:#?}.

Pretty-printing with #?:

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

let origin = Point { x: 0, y: 0 };

let expected = "The origin is: Point {
    x: 0,
    y: 0,
}";
assert_eq!(format!("The origin is: {origin:#?}"), expected);
std::io::stdio
pub fn _print(args: fmt::Arguments<'_>)
src::Fruit
Orange = 1
let fruit: Fruit
#[automatically_derived]

Valid forms are:

  • #[automatically_derived]
core::macros::builtin
macro derive

Attribute macro used to apply derive macros.

See the reference for more info.

src::Fruit
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result

Examples

use std::fmt;

struct Position {
    longitude: f32,
    latitude: f32,
}

impl fmt::Debug for Position {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("")
         .field(&self.longitude)
         .field(&self.latitude)
         .finish()
    }
}

let position = Position { longitude: 1.987, latitude: 2.983 };
assert_eq!(format!("{position:?}"), "(1.987, 2.983)");

assert_eq!(format!("{position:#?}"), "(
    1.987,
    2.983,
)");