Literal expressions

Syntax
LiteralExpression :
      CHAR_LITERAL
   | STRING_LITERAL
   | RAW_STRING_LITERAL
   | BYTE_LITERAL
   | BYTE_STRING_LITERAL
   | RAW_BYTE_STRING_LITERAL
   | C_STRING_LITERAL
   | RAW_C_STRING_LITERAL
   | INTEGER_LITERAL
   | FLOAT_LITERAL
   | true | false

A literal expression is an expression consisting of a single token, rather than a sequence of tokens, that immediately and directly denotes the value it evaluates to, rather than referring to it by name or some other evaluation rule.

A literal is a form of constant expression, so is evaluated (primarily) at compile time.

Each of the lexical literal forms described earlier can make up a literal expression, as can the keywords true and false.

#![allow(unused)]
fn main() {
"hello";   // string type
'5';       // character type
5;         // integer type
}

Character literal expressions

A character literal expression consists of a single CHAR_LITERAL token.

Note: This section is incomplete.

String literal expressions

A string literal expression consists of a single STRING_LITERAL or RAW_STRING_LITERAL token.

Note: This section is incomplete.

Byte literal expressions

A byte literal expression consists of a single BYTE_LITERAL token.

Note: This section is incomplete.

Byte string literal expressions

A string literal expression consists of a single BYTE_STRING_LITERAL or RAW_BYTE_STRING_LITERAL token.

Note: This section is incomplete.

C string literal expressions

A C string literal expression consists of a single C_STRING_LITERAL or RAW_C_STRING_LITERAL token.

Note: This section is incomplete.

Integer literal expressions

An integer literal expression consists of a single INTEGER_LITERAL token.

If the token has a suffix, the suffix must be the name of one of the primitive integer types: u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, or isize, and the expression has that type.

If the token has no suffix, the expression's type is determined by type inference:

  • If an integer type can be uniquely determined from the surrounding program context, the expression has that type.

  • If the program context under-constrains the type, it defaults to the signed 32-bit integer i32.

  • If the program context over-constrains the type, it is considered a static type error.

Examples of integer literal expressions:

#![allow(unused)]
fn main() {
123;                               // type i32
123i32;                            // type i32
123u32;                            // type u32
123_u32;                           // type u32
let a: u64 = 123;                  // type u64

0xff;                              // type i32
0xff_u8;                           // type u8

0o70;                              // type i32
0o70_i16;                          // type i16

0b1111_1111_1001_0000;             // type i32
0b1111_1111_1001_0000i64;          // type i64

0usize;                            // type usize
}

The value of the expression is determined from the string representation of the token as follows:

  • An integer radix is chosen by inspecting the first two characters of the string, as follows:

    • 0b indicates radix 2
    • 0o indicates radix 8
    • 0x indicates radix 16
    • otherwise the radix is 10.
  • If the radix is not 10, the first two characters are removed from the string.

  • Any suffix is removed from the string.

  • Any underscores are removed from the string.

  • The string is converted to a u128 value as if by u128::from_str_radix with the chosen radix. If the value does not fit in u128, it is a compiler error.

  • The u128 value is converted to the expression's type via a numeric cast.

Note: The final cast will truncate the value of the literal if it does not fit in the expression's type. rustc includes a lint check named overflowing_literals, defaulting to deny, which rejects expressions where this occurs.

Note: -1i8, for example, is an application of the negation operator to the literal expression 1i8, not a single integer literal expression. See Overflow for notes on representing the most negative value for a signed type.

Floating-point literal expressions

A floating-point literal expression has one of two forms:

If the token has a suffix, the suffix must be the name of one of the primitive floating-point types: f32 or f64, and the expression has that type.

If the token has no suffix, the expression's type is determined by type inference:

  • If a floating-point type can be uniquely determined from the surrounding program context, the expression has that type.

  • If the program context under-constrains the type, it defaults to f64.

  • If the program context over-constrains the type, it is considered a static type error.

Examples of floating-point literal expressions:

#![allow(unused)]
fn main() {
123.0f64;        // type f64
0.1f64;          // type f64
0.1f32;          // type f32
12E+99_f64;      // type f64
5f32;            // type f32
let x: f64 = 2.; // type f64
}

The value of the expression is determined from the string representation of the token as follows:

  • Any suffix is removed from the string.

  • Any underscores are removed from the string.

  • The string is converted to the expression's type as if by f32::from_str or f64::from_str.

Note: -1.0, for example, is an application of the negation operator to the literal expression 1.0, not a single floating-point literal expression.

Note: inf and NaN are not literal tokens. The f32::INFINITY, f64::INFINITY, f32::NAN, and f64::NAN constants can be used instead of literal expressions. In rustc, a literal large enough to be evaluated as infinite will trigger the overflowing_literals lint check.

Boolean literal expressions

A boolean literal expression consists of one of the keywords true or false.

The expression's type is the primitive boolean type, and its value is:

  • true if the keyword is true
  • false if the keyword is false