Control Flow Option Options

Match

Ah, the good ol' match statement. Generally very powerful, one can use it for measly Option matching:

fn <>(: <>) where : :::: {
    match  {
        () => !("Got some value: {value:?}"),
         => !("Got no value"),
    }
}

Or with more complex match goodness, like match guards and bindings:

fn (: <>, : ) {
    match  {
        () if  >  => !("I am really sorry"),
        () if  ==  => !("What are the odds?"),
        ( @ 1.0..10.0) => !("So close!! Only {value} left..."),
        (_) => !("Some ways to go..."),
         => !("Debt free!"),
    }
}

If Let

Equivalent to checking for a Some while simultaneously unwrapping the containing value:

fn (: <>) {
  if let ( @ ..100.0) =  {
      !("Debt below three digits!! Only {value} remaining."),
  } else {
      !("Unable to perform analysis..."),
  }
}

This allows you to reduce one level of nesting, as compared to the match version:

fn (: <>) {
    match  {
        ( @ ..100.0) => {
            !("Debt below three digits!! Only {value} remaining."),
        },
         => {
            !("Unable to perform analysis..."),
        }
    }
}

Note that if you do not need the containing value, use .is_some() with an if expression:

fn (: <>) {
    if .() {
        !("You have debt."),
    } else {
        !("You do not have debt."),
    }
}

Let Else

The irrefutable version of if let. Use this to unwrap a value, changing control flow if the Option is None:

fn (: <>, : ) {
    let () =  else {
        !("No debt.");
        return;
    }

    let  =  / ;
    !("You owe {debt}.");
    !("You pay {annual_deposit} a year towards your debt.");
    !("You will repay your debt after {} years.", );
}

This allows you to reduce one level of nesting after the unwrapping, as compared to the if let version:

fn (: <>, : ) {
    if let () =  {
        let  =  / ;
        !("You owe {debt}.");
        !("You pay {annual_deposit} a year towards your debt.");
        !("You will repay your debt after {} years.", );
    } else {
        !("No debt.");
    }
}

Note that if you want to panic!() or unreachable!() on None, use .expect() or .unwrap() instead.

fn (: <>, : ) {
    let  = .("Everyone has debt.");

    let  =  / ;
    !("You owe {debt}.");
    !("You pay {annual_deposit} a year towards your debt.");
    !("You will repay your debt after {} years.", );
}
codeintel::block_0ec604bb33dedc85
fn debug_option<T>(option: Option<T>)
where
    T: std::fmt::Debug,
codeintel::block_0ec604bb33dedc85::debug_option
T: Debug
option: Option<T>
core::option
pub enum Option<T> {
    None,
    Some( /* … */ ),
}

The Option type. See the module level documentation for more.

extern crate std

The Rust Standard Library

The Rust Standard Library is the foundation of portable Rust software, a set of minimal and battle-tested shared abstractions for the broader Rust ecosystem. It offers core types, like [Vec<T>] and [Option<T>], library-defined operations on language primitives, standard macros, [I/O] and [multithreading], among many other things.

std is available to all Rust crates by default. Therefore, the standard library can be accessed in use statements through the path std, as in use std::env.

How to read this documentation

If you already know the name of what you are looking for, the fastest way to find it is to use the search button at the top of the page.

Otherwise, you may want to jump to one of these useful sections:

If this is your first time, the documentation for the standard library is written to be casually perused. Clicking on interesting things should generally lead you to interesting places. Still, there are important bits you don’t want to miss, so read on for a tour of the standard library and its documentation!

Once you are familiar with the contents of the standard library you may begin to find the verbosity of the prose distracting. At this stage in your development you may want to press the “ Summary” button near the top of the page to collapse it into a more skimmable view.

While you are looking at the top of the page, also notice the “Source” link. Rust’s API documentation comes with the source code and you are encouraged to read it. The standard library source is generally high quality and a peek behind the curtains is often enlightening.

What is in the standard library documentation?

First of all, The Rust Standard Library is divided into a number of focused modules, all listed further down this page. These modules are the bedrock upon which all of Rust is forged, and they have mighty names like [std::slice] and [std::cmp]. Modules’ documentation typically includes an overview of the module along with examples, and are a smart place to start familiarizing yourself with the library.

Second, implicit methods on primitive types are documented here. This can be a source of confusion for two reasons:

  1. While primitives are implemented by the compiler, the standard libraryimplements methods directly on the primitive types (and it is the onlylibrary that does so), which are documented in the section on primitives.
  2. The standard library exports many modules with the same name as primitive types. These define additional items related to the primitivetype, but not the all-important methods.

So for example there is a page for the primitive type char that lists all the methods that can be called on characters (very useful), and there is a page for the module std::char that documents iterator and error types created by these methods (rarely useful).

Note the documentation for the primitives [str] and [T] (also called ‘slice’). Many method calls on String and [Vec<T>] are actually calls to methods on [str] and [T] respectively, via deref coercions.

Third, the standard library defines [The Rust Prelude], a small collection of items - mostly traits - that are imported into every module of every crate. The traits in the prelude are pervasive, making the prelude documentation a good entry point to learning about the library.

And finally, the standard library exports a number of standard macros, and lists them on this page (technically, not all of the standard macros are defined by the standard library - some are defined by the compiler - but they are documented here the same). Like the prelude, the standard macros are imported by default into all crates.

Contributing changes to the documentation

Check out the Rust contribution guidelines here. The source for this documentation can be found on GitHub in the ‘library/std/’ directory. To contribute changes, make sure you read the guidelines first, then submit pull-requests for your suggested changes.

Contributions are appreciated! If you see a part of the docs that can be improved, submit a PR, or chat with us first on Zulip #docs.

A Tour of The Rust Standard Library

The rest of this crate documentation is dedicated to pointing out notable features of The Rust Standard Library.

Containers and collections

The option and result modules define optional and error-handling types, [Option<T>] and [Result<T, E>]. The iter module defines Rust’s iterator trait, Iterator, which works with the for loop to access collections.

The standard library exposes three common ways to deal with contiguous regions of memory:

  • [Vec<T>] - A heap-allocated vector that is resizable at runtime.
  • [T; N] - An inline array with a fixed size at compile time.
  • [T] - A dynamically sized slice into any other kind of contiguousstorage, whether heap-allocated or not.

Slices can only be handled through some kind of pointer, and as such come in many flavors such as:

  • &[T] - shared slice
  • &mut [T] - mutable slice
  • Box<[T]> - owned slice

[str], a UTF-8 string slice, is a primitive type, and the standard library defines many methods for it. Rust [str]s are typically accessed as immutable references: &str. Use the owned String for building and mutating strings.

For converting to strings use the format macro, and for converting from strings use the [FromStr] trait.

Data may be shared by placing it in a reference-counted box or the [Rc] type, and if further contained in a [Cell] or [RefCell], may be mutated as well as shared. Likewise, in a concurrent setting it is common to pair an atomically-reference-counted box, [Arc], with a [Mutex] to get the same effect.

The collections module defines maps, sets, linked lists and other typical collection types, including the common [HashMap<K, V>].

Platform abstractions and I/O

Besides basic data types, the standard library is largely concerned with abstracting over differences in common platforms, most notably Windows and Unix derivatives.

Common types of I/O, including [files], [TCP], and [UDP], are defined in the io, fs, and net modules.

The thread module contains Rust’s threading abstractions. sync contains further primitive shared memory types, including [atomic], [mpmc] and [mpsc], which contains the channel types for message passing.

Use before and after main()

Many parts of the standard library are expected to work before and after main(); but this is not guaranteed or ensured by tests. It is recommended that you write your own tests and run them on each platform you wish to support. This means that use of std before/after main, especially of features that interact with the OS or global state, is exempted from stability and portability guarantees and instead only provided on a best-effort basis. Nevertheless bug reports are appreciated.

On the other hand core and alloc are most likely to work in such environments with the caveat that any hookable behavior such as panics, oom handling or allocators will also depend on the compatibility of the hooks.

Some features may also behave differently outside main, e.g. stdio could become unbuffered, some panics might turn into aborts, backtraces might not get symbolicated or similar.

Non-exhaustive list of known limitations:

  • after-main use of thread-locals, which also affects additional features:
  • under UNIX, before main, file descriptors 0, 1, and 2 may be unchanged(they are guaranteed to be open during main,and are opened to /dev/null O_RDWR if they weren’t open on program start)
alloc
pub mod fmt

Utilities for formatting and printing Strings.

This module contains the runtime support for the format syntax extension. This macro is implemented in the compiler to emit calls to this module in order to format arguments at runtime into strings.

Usage

The format macro is intended to be familiar to those coming from C’s printf/fprintf functions or Python’s str.format function.

Some examples of the format extension are:

format!("Hello");                 // => "Hello"
format!("Hello, {}!", "world");   // => "Hello, world!"
format!("The number is {}", 1);   // => "The number is 1"
format!("{:?}", (3, 4));          // => "(3, 4)"
format!("{value}", value=4);      // => "4"
let people = "Rustaceans";
format!("Hello {people}!");       // => "Hello Rustaceans!"
format!("{} {}", 1, 2);           // => "1 2"
format!("{:04}", 42);             // => "0042" with leading zeros
format!("{:#?}", (100, 200));     // => "(
                                  //       100,
                                  //       200,
                                  //     )"

From these, you can see that the first argument is a format string. It is required by the compiler for this to be a string literal; it cannot be a variable passed in (in order to perform validity checking). The compiler will then parse the format string and determine if the list of arguments provided is suitable to pass to this format string.

To convert a single value to a string, use the [to_string] method. This will use the Display formatting trait.

Positional parameters

Each formatting argument is allowed to specify which value argument it’s referencing, and if omitted it is assumed to be “the next argument”. For example, the format string {} {} {} would take three parameters, and they would be formatted in the same order as they’re given. The format string {2} {1} {0}, however, would format arguments in reverse order.

Things can get a little tricky once you start intermingling the two types of positional specifiers. The “next argument” specifier can be thought of as an iterator over the argument. Each time a “next argument” specifier is seen, the iterator advances. This leads to behavior like this:

format!("{1} {} {0} {}", 1, 2); // => "2 1 1 2"

The internal iterator over the argument has not been advanced by the time the first {} is seen, so it prints the first argument. Then upon reaching the second {}, the iterator has advanced forward to the second argument. Essentially, parameters that explicitly name their argument do not affect parameters that do not name an argument in terms of positional specifiers.

A format string is required to use all of its arguments, otherwise it is a compile-time error. You may refer to the same argument more than once in the format string.

Named parameters

Rust itself does not have a Python-like equivalent of named parameters to a function, but the format macro is a syntax extension that allows it to leverage named parameters. Named parameters are listed at the end of the argument list and have the syntax:

identifier '=' expression

For example, the following format expressions all use named arguments:

format!("{argument}", argument = "test");   // => "test"
format!("{name} {}", 1, name = 2);          // => "2 1"
format!("{a} {c} {b}", a="a", b='b', c=3);  // => "a 3 b"

If a named parameter does not appear in the argument list, format! will reference a variable with that name in the current scope.

let argument = 2 + 2;
format!("{argument}");   // => "4"

fn make_string(a: u32, b: &str) -> String {
    format!("{b} {a}")
}
make_string(927, "label"); // => "label 927"

It is not valid to put positional parameters (those without names) after arguments that have names. Like with positional parameters, it is not valid to provide named parameters that are unused by the format string.

Formatting Parameters

Each argument being formatted can be transformed by a number of formatting parameters (corresponding to format_spec in the syntax). These parameters affect the string representation of what’s being formatted.

The colon : in format syntax divides identifier of the input data and the formatting options, the colon itself does not change anything, only introduces the options.

let a = 5;
let b = &a;
println!("{a:e} {b:p}"); // => 5e0 0x7ffe37b7273c

Width

// All of these print "Hello x    !"
println!("Hello {:5}!", "x");
println!("Hello {:1$}!", "x", 5);
println!("Hello {1:0$}!", 5, "x");
println!("Hello {:width$}!", "x", width = 5);
let width = 5;
println!("Hello {:width$}!", "x");

This is a parameter for the “minimum width” that the format should take up. If the value’s string does not fill up this many characters, then the padding specified by fill/alignment will be used to take up the required space (see below).

The value for the width can also be provided as a usize in the list of parameters by adding a postfix $, indicating that the second argument is a usize specifying the width.

Referring to an argument with the dollar syntax does not affect the “next argument” counter, so it’s usually a good idea to refer to arguments by position, or use named arguments.

Fill/Alignment

assert_eq!(format!("Hello {:<5}!", "x"),  "Hello x    !");
assert_eq!(format!("Hello {:-<5}!", "x"), "Hello x----!");
assert_eq!(format!("Hello {:^5}!", "x"),  "Hello   x  !");
assert_eq!(format!("Hello {:>5}!", "x"),  "Hello     x!");

The optional fill character and alignment is provided normally in conjunction with the width parameter. It must be defined before width, right after the :. This indicates that if the value being formatted is smaller than width some extra characters will be printed around it. Filling comes in the following variants for different alignments:

  • [fill]< - the argument is left-aligned in width columns
  • [fill]^ - the argument is center-aligned in width columns
  • [fill]> - the argument is right-aligned in width columns

The default fill/alignment for non-numerics is a space and left-aligned. The default for numeric formatters is also a space character but with right-alignment. If the 0 flag (see below) is specified for numerics, then the implicit fill character is 0.

Note that alignment might not be implemented by some types. In particular, it is not generally implemented for the Debug trait. A good way to ensure padding is applied is to format your input, then pad this resulting string to obtain your output:

println!("Hello {:^15}!", format!("{:?}", Some("hi"))); // => "Hello   Some("hi")   !"

Sign/#/0

assert_eq!(format!("Hello {:+}!", 5), "Hello +5!");
assert_eq!(format!("{:#x}!", 27), "0x1b!");
assert_eq!(format!("Hello {:05}!", 5),  "Hello 00005!");
assert_eq!(format!("Hello {:05}!", -5), "Hello -0005!");
assert_eq!(format!("{:#010x}!", 27), "0x0000001b!");

These are all flags altering the behavior of the formatter.

  • + - This is intended for numeric types and indicates that the sign should always be printed. By default only the negative sign of signed values is printed, and the sign of positive or unsigned values is omitted. This flag indicates that the correct sign (+ or -) should always be printed.

  • - - Currently not used

  • # - This flag indicates that the “alternate” form of printing should be used. The alternate forms are:

    • #? - pretty-print the Debug formatting (adds linebreaks and indentation)
    • #x - precedes the argument with a 0x
    • #X - precedes the argument with a 0x
    • #b - precedes the argument with a 0b
    • #o - precedes the argument with a 0oSee Formatting traits for a description of what the ?, x, X,b, and o flags do.
  • 0 - This is used to indicate for integer formats that the padding to width should both be done with a 0 character as well as be sign-aware. A format like {:08} would yield 00000001 for the integer 1, while the same format would yield -0000001 for the integer -1. Notice that the negative version has one fewer zero than the positive version. Note that padding zeros are always placed after the sign (if any) and before the digits. When used together with the # flag, a similar rule applies: padding zeros are inserted after the prefix but before the digits. The prefix is included in the total width. This flag overrides the fill character and alignment flag.

Precision

For non-numeric types, this can be considered a “maximum width”. If the resulting string is longer than this width, then it is truncated down to this many characters and that truncated value is emitted with proper fill, alignment and width if those parameters are set.

For integral types, this is ignored.

For floating-point types, this indicates how many digits after the decimal point should be printed.

There are three possible ways to specify the desired precision:

  1. An integer .N:

    the integer N itself is the precision.

  2. An integer or name followed by dollar sign .N$:

    use format argument N (which must be a usize) as the precision.

  3. An asterisk .*:

    .* means that this {...} is associated with two format inputs rather than one:

    • If a format string in the fashion of {:<spec>.*} is used, then the first input holdsthe usize precision, and the second holds the value to print.
    • If a format string in the fashion of {<arg>:<spec>.*} is used, then the <arg> partrefers to the value to print, and the precision is taken like it was specified with anomitted positional parameter ({} instead of {<arg>:}).

For example, the following calls all print the same thing Hello x is 0.01000:

// Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)}
println!("Hello {0} is {1:.5}", "x", 0.01);

// Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)}
println!("Hello {1} is {2:.0$}", 5, "x", 0.01);

// Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
println!("Hello {0} is {2:.1$}", "x", 5, 0.01);

// Hello {next arg -> arg 0 ("x")} is {second of next two args -> arg 2 (0.01) with precision
//                          specified in first of next two args -> arg 1 (5)}
println!("Hello {} is {:.*}",    "x", 5, 0.01);

// Hello {arg 1 ("x")} is {arg 2 (0.01) with precision
//                          specified in next arg -> arg 0 (5)}
println!("Hello {1} is {2:.*}",  5, "x", 0.01);

// Hello {next arg -> arg 0 ("x")} is {arg 2 (0.01) with precision
//                          specified in next arg -> arg 1 (5)}
println!("Hello {} is {2:.*}",   "x", 5, 0.01);

// Hello {next arg -> arg 0 ("x")} is {arg "number" (0.01) with precision specified
//                          in arg "prec" (5)}
println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);

While these:

println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");

print three significantly different things:

Hello, `1234.560` has 3 fractional digits
Hello, `123` has 3 characters
Hello, `     123` has 3 right-aligned characters

When truncating these values, Rust uses round half-to-even, which is the default rounding mode in IEEE 754. For example,

print!("{0:.1$e}", 12345, 3);
print!("{0:.1$e}", 12355, 3);

Would return:

1.234e4
1.236e4

Localization

In some programming languages, the behavior of string formatting functions depends on the operating system’s locale setting. The format functions provided by Rust’s standard library do not have any concept of locale and will produce the same results on all systems regardless of user configuration.

For example, the following code will always print 1.5 even if the system locale uses a decimal separator other than a dot.

println!("The value is {}", 1.5);

Escaping

The literal characters { and } may be included in a string by preceding them with the same character. For example, the { character is escaped with {{ and the } character is escaped with }}.

assert_eq!(format!("Hello {{}}"), "Hello {}");
assert_eq!(format!("{{ Hello"), "{ Hello");

Syntax

To summarize, here you can find the full grammar of format strings. The syntax for the formatting language used is drawn from other languages, so it should not be too alien. Arguments are formatted with Python-like syntax, meaning that arguments are surrounded by {} instead of the C-like %. The actual grammar for the formatting syntax is:

format_string := text [ maybe_format text ] *
maybe_format := '{' '{' | '}' '}' | format
format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}'
argument := integer | identifier

format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]
fill := character
align := '<' | '^' | '>'
sign := '+' | '-'
width := count
precision := count | '*'
type := '?' | 'x?' | 'X?' | 'o' | 'x' | 'X' | 'p' | 'b' | 'e' | 'E'
count := parameter | integer
parameter := argument '$'

In the above grammar,

  • text must not contain any '{' or '}' characters,
  • ws is any character for which char::is_whitespace returns true, has no semanticmeaning and is completely optional,
  • integer is a decimal integer that may contain leading zeroes and must fit into an usize and
  • identifier is an IDENTIFIER_OR_KEYWORD (not an IDENTIFIER) as defined by the Rust language reference.

Formatting traits

When requesting that an argument be formatted with a particular type, you are actually requesting that an argument ascribes to a particular trait. This allows multiple actual types to be formatted via {:x} (like i8 as well as isize). The current mapping of types to traits is:

What this means is that any type of argument which implements the fmt::Binary trait can then be formatted with {:b}. Implementations are provided for these traits for a number of primitive types by the standard library as well. If no format is specified (as in {} or {:6}), then the format trait used is the Display trait.

When implementing a format trait for your own type, you will have to implement a method of the signature:

fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

Your type will be passed as self by-reference, and then the function should emit output into the Formatter f which implements fmt::Write. It is up to each format trait implementation to correctly adhere to the requested formatting parameters. The values of these parameters can be accessed with methods of the Formatter struct. In order to help with this, the Formatter struct also provides some helper methods.

Additionally, the return value of this function is [fmt::Result] which is a type alias of [Result]<(), [std::fmt::Error]>. Formatting implementations should ensure that they propagate errors from the Formatter (e.g., when calling write). However, they should never return errors spuriously. That is, a formatting implementation must and may only return an error if the passed-in Formatter returns an error. This is because, contrary to what the function signature might suggest, string formatting is an infallible operation. This function only returns a Result because writing to the underlying stream might fail and it must provide a way to propagate the fact that an error has occurred back up the stack.

An example of implementing the formatting traits would look like:

use std::fmt;

#[derive(Debug)]
struct Vector2D {
    x: isize,
    y: isize,
}

impl fmt::Display for Vector2D {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // The `f` value implements the `Write` trait, which is what the
        // write! macro is expecting. Note that this formatting ignores the
        // various flags provided to format strings.
        write!(f, "({}, {})", self.x, self.y)
    }
}

// Different traits allow different forms of output of a type. The meaning
// of this format is to print the magnitude of a vector.
impl fmt::Binary for Vector2D {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let magnitude = (self.x * self.x + self.y * self.y) as f64;
        let magnitude = magnitude.sqrt();

        // Respect the formatting flags by using the helper method
        // `pad_integral` on the Formatter object. See the method
        // documentation for details, and the function `pad` can be used
        // to pad strings.
        let decimals = f.precision().unwrap_or(3);
        let string = format!("{magnitude:.decimals$}");
        f.pad_integral(true, "", &string)
    }
}

fn main() {
    let myvector = Vector2D { x: 3, y: 4 };

    println!("{myvector}");       // => "(3, 4)"
    println!("{myvector:?}");     // => "Vector2D {x: 3, y:4}"
    println!("{myvector:10.3b}"); // => "     5.000"
}

fmt::Display vs fmt::Debug

These two formatting traits have distinct purposes:

  • fmt::Display implementations assert that the type can be faithfullyrepresented as a UTF-8 string at all times. It is not expected thatall types implement the Display trait.
  • fmt::Debug implementations should be implemented for all public types.Output will typically represent the internal state as faithfully as possible.The purpose of the Debug trait is to facilitate debugging Rust code. Inmost cases, using #[derive(Debug)] is sufficient and recommended.

Some examples of the output from both traits:

assert_eq!(format!("{} {:?}", 3, 4), "3 4");
assert_eq!(format!("{} {:?}", 'a', 'b'), "a 'b'");
assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\"");
core::fmt
pub trait Debug
where
    Self: PointeeSized,

? 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);
core::option::Option
Some(T)

Some value of type T.

let value: T
std::macros
macro_rules! eprintln

Prints to the standard error, with a newline.

Equivalent to the [println!] macro, except that output goes to [io::stderr] instead of [io::stdout]. See [println!] for example usage.

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

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

Panics

Panics if writing to io::stderr fails.

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

Examples

eprintln!("Error: Could not complete task");
core::option::Option
None

No value.

codeintel::block_09b21eb8d228ca20
fn check_debt(debt: Option<f64>, net_worth: f64)
debt: Option<f64>
f64

A 64-bit floating-point type (specifically, the “binary64” type defined in IEEE 754-2008).

This type is very similar to prim@f32, but has increased precision by using twice as many bits. Please see the documentation for f32 or Wikipedia on double-precision values for more information.

See also the std::f64::consts module.

net_worth: f64
let value: f64
codeintel::block_0b0df1ea2ff80976
fn analyze_debt(debt: Option<f64>)
codeintel::block_976fea995103908e
fn analyze_debt(debt: Option<f64>)
codeintel::block_0c7905a89bb03037
fn analyze_debt(debt: Option<f64>)
core::option::Option
impl<T> Option<T>
pub const fn is_some(&self) -> bool

Returns true if the option is a Some value.

Examples

let x: Option<u32> = Some(2);
assert_eq!(x.is_some(), true);

let x: Option<u32> = None;
assert_eq!(x.is_some(), false);
codeintel::block_a2254fbf49fa2906
fn calculate_years_to_repay(debt: Option<f64>, annual_deposit: f64)
annual_deposit: f64
let amount: f64
let repay_years: f64
codeintel::block_b0ecc6a24691ec50
fn calculate_years_to_repay(debt: Option<f64>, annual_deposit: f64)
codeintel::block_4b57ed58e4f09ca2
fn calculate_years_to_repay(debt: Option<f64>, annual_deposit: f64)
core::option::Option
impl<T> Option<T>
pub const fn expect(self, msg: &str) -> T

Returns the contained Some value, consuming the self value.

Panics

Panics if the value is a None with a custom panic message provided by msg.

Examples

let x = Some("value");
assert_eq!(x.expect("fruits are healthy"), "value");
let x: Option<&str> = None;
x.expect("fruits are healthy"); // panics with `fruits are healthy`