]>
Commit | Line | Data |
---|---|---|
f035d41b XL |
1 | # `const fn` |
2 | ||
3 | Initially added: ![Minimum Rust version: 1.31](https://img.shields.io/badge/Minimum%20Rust%20Version-1.31-brightgreen.svg) | |
4 | ||
5 | Expanded in many releases, see each aspect below for more details. | |
6 | ||
7 | A `const fn` allows you to execute code in a "const context." For example: | |
8 | ||
29967ef6 | 9 | ```rust |
f035d41b XL |
10 | const fn five() -> i32 { |
11 | 5 | |
12 | } | |
13 | ||
14 | const FIVE: i32 = five(); | |
15 | ``` | |
16 | ||
17 | You cannot execute arbitrary code; the reasons why boil down to "you can | |
18 | destroy the type system." The details are a bit too much to put here, but the | |
19 | core idea is that `const fn` started off allowing the absolutely minimal | |
20 | subset of the language, and has slowly added more abilities over time. | |
21 | Therefore, while you can create a `const fn` in Rust 1.31, you cannot do much | |
22 | with it. This is why we didn't add `const fn` to the Rust 2018 section; it | |
23 | truly didn't become useful until after the release of the 2018 edition. This | |
24 | means that if you read this document top to bottom, the earlier versions may | |
25 | describe restrictions that are relaxed in later versions. | |
26 | ||
27 | Additionally, this has allowed more and more of the standard library to be | |
28 | made `const`, we won't put all of those changes here, but you should know | |
29 | that it is becoming more `const` over time. | |
30 | ||
31 | ## Arithmetic and comparison operators on integers | |
32 | ||
33 | ![Minimum Rust version: 1.31](https://img.shields.io/badge/Minimum%20Rust%20Version-1.31-brightgreen.svg) | |
34 | ||
35 | You can do arithmetic on integer literals: | |
36 | ||
29967ef6 | 37 | ```rust |
f035d41b XL |
38 | const fn foo() -> i32 { |
39 | 5 + 6 | |
40 | } | |
41 | ``` | |
42 | ||
43 | ## Many boolean operators | |
44 | ||
45 | ![Minimum Rust version: 1.31](https://img.shields.io/badge/Minimum%20Rust%20Version-1.31-brightgreen.svg) | |
46 | ||
47 | You can use boolean operators other than `&&` and `||`, because they short-circut evaluation: | |
48 | ||
29967ef6 | 49 | ```rust |
f035d41b XL |
50 | const fn mask(val: u8) -> u8 { |
51 | let mask = 0x0f; | |
52 | ||
53 | mask & val | |
54 | } | |
55 | ``` | |
56 | ||
57 | ## Constructing arrays, structs, enums, and tuples | |
58 | ||
59 | ![Minimum Rust version: 1.31](https://img.shields.io/badge/Minimum%20Rust%20Version-1.31-brightgreen.svg) | |
60 | ||
61 | You can create arrays, structs, enums, and tuples: | |
62 | ||
29967ef6 | 63 | ```rust |
f035d41b XL |
64 | struct Point { |
65 | x: i32, | |
66 | y: i32, | |
67 | } | |
68 | ||
69 | enum Error { | |
70 | Incorrect, | |
71 | FileNotFound, | |
72 | } | |
73 | ||
74 | const fn foo() { | |
75 | let array = [1, 2, 3]; | |
76 | ||
77 | let point = Point { | |
78 | x: 5, | |
79 | y: 10, | |
80 | }; | |
81 | ||
82 | let error = Error::FileNotFound; | |
83 | ||
84 | let tuple = (1, 2, 3); | |
85 | } | |
86 | ``` | |
87 | ||
88 | ## Calls to other const fns | |
89 | ||
90 | ![Minimum Rust version: 1.31](https://img.shields.io/badge/Minimum%20Rust%20Version-1.31-brightgreen.svg) | |
91 | ||
92 | You can call `const fn` from a `const fn`: | |
93 | ||
94 | ||
29967ef6 | 95 | ```rust |
f035d41b XL |
96 | const fn foo() -> i32 { |
97 | 5 | |
98 | } | |
99 | ||
100 | const fn bar() -> i32 { | |
101 | foo() | |
102 | } | |
103 | ``` | |
104 | ||
105 | ## Index expressions on arrays and slices | |
106 | ||
107 | ![Minimum Rust version: 1.31](https://img.shields.io/badge/Minimum%20Rust%20Version-1.31-brightgreen.svg) | |
108 | ||
109 | You can index into an array or slice: | |
110 | ||
29967ef6 | 111 | ```rust |
f035d41b XL |
112 | const fn foo() -> i32 { |
113 | let array = [1, 2, 3]; | |
114 | ||
115 | array[1] | |
116 | } | |
117 | ``` | |
118 | ||
119 | ## Field accesses on structs and tuples | |
120 | ||
121 | ![Minimum Rust version: 1.31](https://img.shields.io/badge/Minimum%20Rust%20Version-1.31-brightgreen.svg) | |
122 | ||
123 | You can access parts of a struct or tuple: | |
124 | ||
29967ef6 | 125 | ```rust |
f035d41b XL |
126 | struct Point { |
127 | x: i32, | |
128 | y: i32, | |
129 | } | |
130 | ||
131 | const fn foo() { | |
132 | let point = Point { | |
133 | x: 5, | |
134 | y: 10, | |
135 | }; | |
136 | ||
137 | let tuple = (1, 2, 3); | |
138 | ||
139 | point.x; | |
140 | tuple.0; | |
141 | } | |
142 | ``` | |
143 | ||
144 | ## Reading from constants | |
145 | ||
146 | ![Minimum Rust version: 1.31](https://img.shields.io/badge/Minimum%20Rust%20Version-1.31-brightgreen.svg) | |
147 | ||
148 | You can read from a constant: | |
149 | ||
29967ef6 | 150 | ```rust |
f035d41b XL |
151 | const FOO: i32 = 5; |
152 | ||
153 | const fn foo() -> i32 { | |
154 | FOO | |
155 | } | |
156 | ``` | |
157 | ||
158 | Note that this is *only* `const`, not `static`. | |
159 | ||
160 | ## & and * of references | |
161 | ||
162 | ![Minimum Rust version: 1.31](https://img.shields.io/badge/Minimum%20Rust%20Version-1.31-brightgreen.svg) | |
163 | ||
164 | You can create and de-reference references: | |
165 | ||
29967ef6 | 166 | ```rust |
f035d41b XL |
167 | const fn foo(r: &i32) { |
168 | *r; | |
169 | ||
170 | &5; | |
171 | } | |
172 | ``` | |
173 | ||
174 | ## Casts, except for raw pointer to integer casts | |
175 | ||
176 | ![Minimum Rust version: 1.31](https://img.shields.io/badge/Minimum%20Rust%20Version-1.31-brightgreen.svg) | |
177 | ||
178 | You may cast things, except for raw pointers may not be casted to an integer: | |
179 | ||
29967ef6 | 180 | ```rust |
f035d41b XL |
181 | const fn foo() { |
182 | let x: usize = 5; | |
183 | ||
184 | x as i32; | |
185 | } | |
186 | ``` | |
187 | ||
188 | ## Irrefutable destructuring patterns | |
189 | ||
190 | ![Minimum Rust version: 1.33](https://img.shields.io/badge/Minimum%20Rust%20Version-1.33-brightgreen.svg) | |
191 | ||
192 | You can use irrefutable patterns that destructure values. For example: | |
193 | ||
29967ef6 | 194 | ```rust |
f035d41b XL |
195 | const fn foo((x, y): (u8, u8)) { |
196 | // ... | |
197 | } | |
198 | ``` | |
199 | ||
200 | Here, `foo` destructures the tuple into `x` and `y`. `if let` is another | |
201 | place that uses irrefutable patterns. | |
202 | ||
203 | ## `let` bindings | |
204 | ||
205 | ![Minimum Rust version: 1.33](https://img.shields.io/badge/Minimum%20Rust%20Version-1.33-brightgreen.svg) | |
206 | ||
207 | You can use both mutable and immutable `let` bindings: | |
208 | ||
29967ef6 | 209 | ```rust |
f035d41b XL |
210 | const fn foo() { |
211 | let x = 5; | |
212 | let mut y = 10; | |
213 | } | |
214 | ``` | |
215 | ||
216 | ## Assignment | |
217 | ||
218 | ![Minimum Rust version: 1.33](https://img.shields.io/badge/Minimum%20Rust%20Version-1.33-brightgreen.svg) | |
219 | ||
220 | You can use assignment and assignment operators: | |
221 | ||
29967ef6 | 222 | ```rust |
f035d41b XL |
223 | const fn foo() { |
224 | let mut x = 5; | |
225 | x = 10; | |
226 | } | |
227 | ``` | |
228 | ||
229 | ## Calling `unsafe fn` | |
230 | ||
231 | ![Minimum Rust version: 1.33](https://img.shields.io/badge/Minimum%20Rust%20Version-1.33-brightgreen.svg) | |
232 | ||
1b1a35ee | 233 | You can call an `unsafe fn` inside a `const fn`: |
f035d41b | 234 | |
29967ef6 | 235 | ```rust |
f035d41b XL |
236 | const unsafe fn foo() -> i32 { 5 } |
237 | ||
238 | const fn bar() -> i32 { | |
239 | unsafe { foo() } | |
240 | } | |
1b1a35ee | 241 | ``` |