Skip to content

Commit b85bbf4

Browse files
authored
Merge pull request #1177 from mattheww/2022-03_numeric_literals
Numeric literal expressions and literal suffixes
2 parents c97d14f + 2c78399 commit b85bbf4

File tree

2 files changed

+304
-117
lines changed

2 files changed

+304
-117
lines changed

src/expressions/literal-expr.md

+148-3
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,164 @@
88
>    | [BYTE_LITERAL]\
99
>    | [BYTE_STRING_LITERAL]\
1010
>    | [RAW_BYTE_STRING_LITERAL]\
11-
>    | [INTEGER_LITERAL]\
11+
>    | [INTEGER_LITERAL][^out-of-range]\
1212
>    | [FLOAT_LITERAL]\
1313
>    | [BOOLEAN_LITERAL]
14+
>
15+
> [^out-of-range]: A value ≥ 2<sup>128</sup> is not allowed.
1416
15-
A _literal expression_ consists of one of the [literal](../tokens.md#literals) forms described earlier.
16-
It directly describes a number, character, string, or boolean value.
17+
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.
18+
19+
A literal is a form of [constant expression], so is evaluated (primarily) at compile time.
20+
21+
Each of the lexical [literal][literal tokens] forms described earlier can make up a literal expression.
1722

1823
```rust
1924
"hello"; // string type
2025
'5'; // character type
2126
5; // integer type
2227
```
2328

29+
## Character literal expressions
30+
31+
A character literal expression consists of a single [CHAR_LITERAL] token.
32+
33+
> **Note**: This section is incomplete.
34+
35+
## String literal expressions
36+
37+
A string literal expression consists of a single [STRING_LITERAL] or [RAW_STRING_LITERAL] token.
38+
39+
> **Note**: This section is incomplete.
40+
41+
## Byte literal expressions
42+
43+
A byte literal expression consists of a single [BYTE_LITERAL] token.
44+
45+
> **Note**: This section is incomplete.
46+
47+
## Byte string literal expressions
48+
49+
A string literal expression consists of a single [BYTE_STRING_LITERAL] or [RAW_BYTE_STRING_LITERAL] token.
50+
51+
> **Note**: This section is incomplete.
52+
53+
## Integer literal expressions
54+
55+
An integer literal expression consists of a single [INTEGER_LITERAL] token.
56+
57+
If the token has a [suffix], the suffix will be the name of one of the [primitive integer types][numeric types]: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `u128`, `i128`, `usize`, or `isize`, and the expression has that type.
58+
59+
If the token has no suffix, the expression's type is determined by type inference:
60+
61+
* If an integer type can be _uniquely_ determined from the surrounding program context, the expression has that type.
62+
63+
* If the program context under-constrains the type, it defaults to the signed 32-bit integer `i32`.
64+
65+
* If the program context over-constrains the type, it is considered a static type error.
66+
67+
Examples of integer literal expressions:
68+
69+
```rust
70+
123; // type i32
71+
123i32; // type i32
72+
123u32; // type u32
73+
123_u32; // type u32
74+
let a: u64 = 123; // type u64
75+
76+
0xff; // type i32
77+
0xff_u8; // type u8
78+
79+
0o70; // type i32
80+
0o70_i16; // type i16
81+
82+
0b1111_1111_1001_0000; // type i32
83+
0b1111_1111_1001_0000i64; // type i64
84+
85+
0usize; // type usize
86+
```
87+
88+
The value of the expression is determined from the string representation of the token as follows:
89+
90+
* An integer radix is chosen by inspecting the first two characters of the string, as follows:
91+
92+
* `0b` indicates radix 2
93+
* `0o` indicates radix 8
94+
* `0x` indicates radix 16
95+
* otherwise the radix is 10.
96+
97+
* If the radix is not 10, the first two characters are removed from the string.
98+
99+
* Any underscores are removed from the string.
100+
101+
* The string is converted to a `u128` value as if by [`u128::from_str_radix`] with the chosen radix.
102+
If the value does not fit in `u128`, the expression is rejected by the parser.
103+
104+
* The `u128` value is converted to the expression's type via a [numeric cast].
105+
106+
> **Note**: The final cast will truncate the value of the literal if it does not fit in the expression's type.
107+
> `rustc` includes a [lint check] named `overflowing_literals`, defaulting to `deny`, which rejects expressions where this occurs.
108+
109+
> **Note**: `-1i8`, for example, is an application of the [negation operator] to the literal expression `1i8`, not a single integer literal expression.
110+
111+
## Floating-point literal expressions
112+
113+
A floating-point literal expression consists of a single [FLOAT_LITERAL] token.
114+
115+
If the token has a [suffix], the suffix will be the name of one of the [primitive floating-point types][floating-point types]: `f32` or `f64`, and the expression has that type.
116+
117+
If the token has no suffix, the expression's type is determined by type inference:
118+
119+
* If a floating-point type can be _uniquely_ determined from the surrounding program context, the expression has that type.
120+
121+
* If the program context under-constrains the type, it defaults to `f64`.
122+
123+
* If the program context over-constrains the type, it is considered a static type error.
124+
125+
Examples of floating-point literal expressions:
126+
127+
```rust
128+
123.0f64; // type f64
129+
0.1f64; // type f64
130+
0.1f32; // type f32
131+
12E+99_f64; // type f64
132+
5f32; // type f32
133+
let x: f64 = 2.; // type f64
134+
```
135+
136+
The value of the expression is determined from the string representation of the token as follows:
137+
138+
* Any underscores are removed from the string.
139+
140+
* The string is converted to the expression's type as if by [`f32::from_str`] or [`f64::from_str`].
141+
142+
> **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.
143+
144+
> **Note**: `inf` and `NaN` are not literal tokens.
145+
> The [`f32::INFINITY`], [`f64::INFINITY`], [`f32::NAN`], and [`f64::NAN`] constants can be used instead of literal expressions.
146+
> In `rustc`, a literal large enough to be evaluated as infinite will trigger the `overflowing_literals` lint check.
147+
148+
## Boolean literal expressions
149+
150+
A boolean literal expression consists of a single [BOOLEAN_LITERAL] token.
151+
152+
> **Note**: This section is incomplete.
153+
154+
[constant expression]: ../const_eval.md#constant-expressions
155+
[floating-point types]: ../types/numeric.md#floating-point-types
156+
[lint check]: ../attributes/diagnostics.md#lint-check-attributes
157+
[literal tokens]: ../tokens.md#literals
158+
[numeric cast]: operator-expr.md#numeric-cast
159+
[numeric types]: ../types/numeric.md
160+
[suffix]: ../tokens.md#suffixes
161+
[negation operator]: operator-expr.md#negation-operators
162+
[`f32::from_str`]: ../../core/primitive.f32.md#method.from_str
163+
[`f32::INFINITY`]: ../../core/primitive.f32.md#associatedconstant.INFINITY
164+
[`f32::NAN`]: ../../core/primitive.f32.md#associatedconstant.NAN
165+
[`f64::from_str`]: ../../core/primitive.f64.md#method.from_str
166+
[`f64::INFINITY`]: ../../core/primitive.f64.md#associatedconstant.INFINITY
167+
[`f64::NAN`]: ../../core/primitive.f64.md#associatedconstant.NAN
168+
[`u128::from_str_radix`]: ../../core/primitive.u128.md#method.from_str_radix
24169
[CHAR_LITERAL]: ../tokens.md#character-literals
25170
[STRING_LITERAL]: ../tokens.md#string-literals
26171
[RAW_STRING_LITERAL]: ../tokens.md#raw-string-literals

0 commit comments

Comments
 (0)