aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-06-04 18:45:37 +0100
committerGitHub <[email protected]>2021-06-04 18:45:37 +0100
commit98395f29a417b37a5969594f0cac5ae23585da85 (patch)
tree3a13913003723f3da843dae8580287b9d33c68eb /crates/ide_db
parent92d91050c4aa48732e7af3bf979aa7ed5aed924d (diff)
parentae1c63fcdd0caf34f41fba62b04e3d868a589f1d (diff)
Merge #9138
9138: feat: Implement hover for lints r=Veykril a=Veykril fixes https://github.com/rust-analyzer/rust-analyzer/issues/8857, fixes https://github.com/rust-analyzer/rust-analyzer/issues/3941 ![URXBanNxYe](https://user-images.githubusercontent.com/3757771/120830905-4bd8da80-c55f-11eb-9f55-ff5a321726fa.gif) We also generate the default lints(and lint groups 🎉) instead now by invoking `rustc -W help` and parsing the output from that. Co-authored-by: Lukas Wirth <[email protected]>
Diffstat (limited to 'crates/ide_db')
-rw-r--r--crates/ide_db/src/helpers.rs1
-rw-r--r--crates/ide_db/src/helpers/generated_lints.rs6918
2 files changed, 6919 insertions, 0 deletions
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs
index 21b48237a..00900cdc2 100644
--- a/crates/ide_db/src/helpers.rs
+++ b/crates/ide_db/src/helpers.rs
@@ -3,6 +3,7 @@ pub mod import_assets;
3pub mod insert_use; 3pub mod insert_use;
4pub mod merge_imports; 4pub mod merge_imports;
5pub mod rust_doc; 5pub mod rust_doc;
6pub mod generated_lints;
6 7
7use std::collections::VecDeque; 8use std::collections::VecDeque;
8 9
diff --git a/crates/ide_db/src/helpers/generated_lints.rs b/crates/ide_db/src/helpers/generated_lints.rs
new file mode 100644
index 000000000..6ccb0478e
--- /dev/null
+++ b/crates/ide_db/src/helpers/generated_lints.rs
@@ -0,0 +1,6918 @@
1//! Generated file, do not edit by hand, see `xtask/src/codegen`
2
3pub struct Lint {
4 pub label: &'static str,
5 pub description: &'static str,
6}
7
8pub const DEFAULT_LINTS: &[Lint] = &[
9 Lint {
10 label: "absolute_paths_not_starting_with_crate",
11 description: r##"fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name"##,
12 },
13 Lint { label: "ambiguous_associated_items", description: r##"ambiguous associated items"## },
14 Lint { label: "anonymous_parameters", description: r##"detects anonymous parameters"## },
15 Lint { label: "arithmetic_overflow", description: r##"arithmetic operation overflows"## },
16 Lint { label: "array_into_iter", description: r##"detects calling `into_iter` on arrays"## },
17 Lint {
18 label: "asm_sub_register",
19 description: r##"using only a subset of a register for inline asm inputs"##,
20 },
21 Lint { label: "bad_asm_style", description: r##"incorrect use of inline assembly"## },
22 Lint {
23 label: "bare_trait_objects",
24 description: r##"suggest using `dyn Trait` for trait objects"##,
25 },
26 Lint {
27 label: "bindings_with_variant_name",
28 description: r##"detects pattern bindings with the same name as one of the matched variants"##,
29 },
30 Lint { label: "box_pointers", description: r##"use of owned (Box type) heap memory"## },
31 Lint {
32 label: "cenum_impl_drop_cast",
33 description: r##"a C-like enum implementing Drop is cast"##,
34 },
35 Lint {
36 label: "clashing_extern_declarations",
37 description: r##"detects when an extern fn has been declared with the same name but different types"##,
38 },
39 Lint {
40 label: "coherence_leak_check",
41 description: r##"distinct impls distinguished only by the leak-check code"##,
42 },
43 Lint {
44 label: "conflicting_repr_hints",
45 description: r##"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice"##,
46 },
47 Lint {
48 label: "confusable_idents",
49 description: r##"detects visually confusable pairs between identifiers"##,
50 },
51 Lint {
52 label: "const_err",
53 description: r##"constant evaluation encountered erroneous expression"##,
54 },
55 Lint {
56 label: "const_evaluatable_unchecked",
57 description: r##"detects a generic constant is used in a type without a emitting a warning"##,
58 },
59 Lint {
60 label: "const_item_mutation",
61 description: r##"detects attempts to mutate a `const` item"##,
62 },
63 Lint { label: "dead_code", description: r##"detect unused, unexported items"## },
64 Lint { label: "deprecated", description: r##"detects use of deprecated items"## },
65 Lint {
66 label: "deprecated_in_future",
67 description: r##"detects use of items that will be deprecated in a future version"##,
68 },
69 Lint {
70 label: "deref_nullptr",
71 description: r##"detects when an null pointer is dereferenced"##,
72 },
73 Lint {
74 label: "disjoint_capture_migration",
75 description: r##"Drop reorder and auto traits error because of `capture_disjoint_fields`"##,
76 },
77 Lint { label: "drop_bounds", description: r##"bounds of the form `T: Drop` are useless"## },
78 Lint {
79 label: "elided_lifetimes_in_paths",
80 description: r##"hidden lifetime parameters in types are deprecated"##,
81 },
82 Lint {
83 label: "ellipsis_inclusive_range_patterns",
84 description: r##"`...` range patterns are deprecated"##,
85 },
86 Lint {
87 label: "explicit_outlives_requirements",
88 description: r##"outlives requirements can be inferred"##,
89 },
90 Lint {
91 label: "exported_private_dependencies",
92 description: r##"public interface leaks type from a private dependency"##,
93 },
94 Lint { label: "forbidden_lint_groups", description: r##"applying forbid to lint-groups"## },
95 Lint {
96 label: "function_item_references",
97 description: r##"suggest casting to a function pointer when attempting to take references to function items"##,
98 },
99 Lint {
100 label: "future_incompatible",
101 description: r##"lint group for: keyword-idents, anonymous-parameters, ellipsis-inclusive-range-patterns, forbidden-lint-groups, illegal-floating-point-literal-pattern, private-in-public, pub-use-of-private-extern-crate, invalid-type-param-default, const-err, unaligned-references, patterns-in-fns-without-body, missing-fragment-specifier, late-bound-lifetime-arguments, order-dependent-trait-objects, coherence-leak-check, tyvar-behind-raw-pointer, bare-trait-objects, absolute-paths-not-starting-with-crate, unstable-name-collisions, where-clauses-object-safety, proc-macro-derive-resolution-fallback, macro-expanded-macro-exports-accessed-by-absolute-paths, ill-formed-attribute-input, conflicting-repr-hints, ambiguous-associated-items, mutable-borrow-reservation-conflict, indirect-structural-match, pointer-structural-match, nontrivial-structural-match, soft-unstable, cenum-impl-drop-cast, const-evaluatable-unchecked, uninhabited-static, unsupported-naked-functions, semicolon-in-expressions-from-macros, legacy-derive-helpers, proc-macro-back-compat, array-into-iter"##,
102 },
103 Lint {
104 label: "ill_formed_attribute_input",
105 description: r##"ill-formed attribute inputs that were previously accepted and used in practice"##,
106 },
107 Lint {
108 label: "illegal_floating_point_literal_pattern",
109 description: r##"floating-point literals cannot be used in patterns"##,
110 },
111 Lint {
112 label: "improper_ctypes",
113 description: r##"proper use of libc types in foreign modules"##,
114 },
115 Lint {
116 label: "improper_ctypes_definitions",
117 description: r##"proper use of libc types in foreign item definitions"##,
118 },
119 Lint {
120 label: "incomplete_features",
121 description: r##"incomplete features that may function improperly in some or all cases"##,
122 },
123 Lint { label: "incomplete_include", description: r##"trailing content in included file"## },
124 Lint {
125 label: "indirect_structural_match",
126 description: r##"constant used in pattern contains value of non-structural-match type in a field or a variant"##,
127 },
128 Lint {
129 label: "ineffective_unstable_trait_impl",
130 description: r##"detects `#[unstable]` on stable trait implementations for stable types"##,
131 },
132 Lint {
133 label: "inline_no_sanitize",
134 description: r##"detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`"##,
135 },
136 Lint {
137 label: "invalid_type_param_default",
138 description: r##"type parameter default erroneously allowed in invalid location"##,
139 },
140 Lint {
141 label: "invalid_value",
142 description: r##"an invalid value is being created (such as a null reference)"##,
143 },
144 Lint {
145 label: "irrefutable_let_patterns",
146 description: r##"detects irrefutable patterns in `if let` and `while let` statements"##,
147 },
148 Lint {
149 label: "keyword_idents",
150 description: r##"detects edition keywords being used as an identifier"##,
151 },
152 Lint { label: "large_assignments", description: r##"detects large moves or copies"## },
153 Lint {
154 label: "late_bound_lifetime_arguments",
155 description: r##"detects generic lifetime arguments in path segments with late bound lifetime parameters"##,
156 },
157 Lint {
158 label: "legacy_derive_helpers",
159 description: r##"detects derive helper attributes that are used before they are introduced"##,
160 },
161 Lint {
162 label: "macro_expanded_macro_exports_accessed_by_absolute_paths",
163 description: r##"macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths"##,
164 },
165 Lint {
166 label: "macro_use_extern_crate",
167 description: r##"the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system"##,
168 },
169 Lint {
170 label: "meta_variable_misuse",
171 description: r##"possible meta-variable misuse at macro definition"##,
172 },
173 Lint { label: "missing_abi", description: r##"No declared ABI for extern declaration"## },
174 Lint {
175 label: "missing_copy_implementations",
176 description: r##"detects potentially-forgotten implementations of `Copy`"##,
177 },
178 Lint {
179 label: "missing_debug_implementations",
180 description: r##"detects missing implementations of Debug"##,
181 },
182 Lint {
183 label: "missing_docs",
184 description: r##"detects missing documentation for public members"##,
185 },
186 Lint {
187 label: "missing_fragment_specifier",
188 description: r##"detects missing fragment specifiers in unused `macro_rules!` patterns"##,
189 },
190 Lint {
191 label: "mixed_script_confusables",
192 description: r##"detects Unicode scripts whose mixed script confusables codepoints are solely used"##,
193 },
194 Lint {
195 label: "mutable_borrow_reservation_conflict",
196 description: r##"reservation of a two-phased borrow conflicts with other shared borrows"##,
197 },
198 Lint {
199 label: "mutable_transmutes",
200 description: r##"mutating transmuted &mut T from &T may cause undefined behavior"##,
201 },
202 Lint {
203 label: "no_mangle_const_items",
204 description: r##"const items will not have their symbols exported"##,
205 },
206 Lint { label: "no_mangle_generic_items", description: r##"generic items must be mangled"## },
207 Lint { label: "non_ascii_idents", description: r##"detects non-ASCII identifiers"## },
208 Lint {
209 label: "non_camel_case_types",
210 description: r##"types, variants, traits and type parameters should have camel case names"##,
211 },
212 Lint {
213 label: "non_fmt_panic",
214 description: r##"detect single-argument panic!() invocations in which the argument is not a format string"##,
215 },
216 Lint {
217 label: "non_shorthand_field_patterns",
218 description: r##"using `Struct { x: x }` instead of `Struct { x }` in a pattern"##,
219 },
220 Lint {
221 label: "non_snake_case",
222 description: r##"variables, methods, functions, lifetime parameters and modules should have snake case names"##,
223 },
224 Lint {
225 label: "non_upper_case_globals",
226 description: r##"static constants should have uppercase identifiers"##,
227 },
228 Lint {
229 label: "nonstandard_style",
230 description: r##"lint group for: non-camel-case-types, non-snake-case, non-upper-case-globals"##,
231 },
232 Lint {
233 label: "nontrivial_structural_match",
234 description: r##"constant used in pattern of non-structural-match type and the constant's initializer expression contains values of non-structural-match types"##,
235 },
236 Lint {
237 label: "noop_method_call",
238 description: r##"detects the use of well-known noop methods"##,
239 },
240 Lint {
241 label: "or_patterns_back_compat",
242 description: r##"detects usage of old versions of or-patterns"##,
243 },
244 Lint {
245 label: "order_dependent_trait_objects",
246 description: r##"trait-object types were treated as different depending on marker-trait order"##,
247 },
248 Lint { label: "overflowing_literals", description: r##"literal out of range for its type"## },
249 Lint {
250 label: "overlapping_range_endpoints",
251 description: r##"detects range patterns with overlapping endpoints"##,
252 },
253 Lint { label: "path_statements", description: r##"path statements with no effect"## },
254 Lint {
255 label: "patterns_in_fns_without_body",
256 description: r##"patterns in functions without body were erroneously allowed"##,
257 },
258 Lint {
259 label: "pointer_structural_match",
260 description: r##"pointers are not structural-match"##,
261 },
262 Lint {
263 label: "private_in_public",
264 description: r##"detect private items in public interfaces not caught by the old implementation"##,
265 },
266 Lint {
267 label: "proc_macro_back_compat",
268 description: r##"detects usage of old versions of certain proc-macro crates"##,
269 },
270 Lint {
271 label: "proc_macro_derive_resolution_fallback",
272 description: r##"detects proc macro derives using inaccessible names from parent modules"##,
273 },
274 Lint {
275 label: "pub_use_of_private_extern_crate",
276 description: r##"detect public re-exports of private extern crates"##,
277 },
278 Lint {
279 label: "redundant_semicolons",
280 description: r##"detects unnecessary trailing semicolons"##,
281 },
282 Lint {
283 label: "renamed_and_removed_lints",
284 description: r##"lints that have been renamed or removed"##,
285 },
286 Lint {
287 label: "rust_2018_compatibility",
288 description: r##"lint group for: keyword-idents, anonymous-parameters, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate"##,
289 },
290 Lint {
291 label: "rust_2018_idioms",
292 description: r##"lint group for: bare-trait-objects, unused-extern-crates, ellipsis-inclusive-range-patterns, elided-lifetimes-in-paths, explicit-outlives-requirements"##,
293 },
294 Lint {
295 label: "rust_2021_compatibility",
296 description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects"##,
297 },
298 Lint {
299 label: "semicolon_in_expressions_from_macros",
300 description: r##"trailing semicolon in macro body used as expression"##,
301 },
302 Lint {
303 label: "single_use_lifetimes",
304 description: r##"detects lifetime parameters that are only used once"##,
305 },
306 Lint {
307 label: "soft_unstable",
308 description: r##"a feature gate that doesn't break dependent crates"##,
309 },
310 Lint {
311 label: "stable_features",
312 description: r##"stable features found in `#[feature]` directive"##,
313 },
314 Lint {
315 label: "temporary_cstring_as_ptr",
316 description: r##"detects getting the inner pointer of a temporary `CString`"##,
317 },
318 Lint {
319 label: "trivial_bounds",
320 description: r##"these bounds don't depend on an type parameters"##,
321 },
322 Lint {
323 label: "trivial_casts",
324 description: r##"detects trivial casts which could be removed"##,
325 },
326 Lint {
327 label: "trivial_numeric_casts",
328 description: r##"detects trivial casts of numeric types which could be removed"##,
329 },
330 Lint {
331 label: "type_alias_bounds",
332 description: r##"bounds in type aliases are not enforced"##,
333 },
334 Lint {
335 label: "tyvar_behind_raw_pointer",
336 description: r##"raw pointer to an inference variable"##,
337 },
338 Lint {
339 label: "unaligned_references",
340 description: r##"detects unaligned references to fields of packed structs"##,
341 },
342 Lint {
343 label: "uncommon_codepoints",
344 description: r##"detects uncommon Unicode codepoints in identifiers"##,
345 },
346 Lint {
347 label: "unconditional_panic",
348 description: r##"operation will cause a panic at runtime"##,
349 },
350 Lint {
351 label: "unconditional_recursion",
352 description: r##"functions that cannot return without calling themselves"##,
353 },
354 Lint { label: "uninhabited_static", description: r##"uninhabited static"## },
355 Lint {
356 label: "unknown_crate_types",
357 description: r##"unknown crate type found in `#[crate_type]` directive"##,
358 },
359 Lint { label: "unknown_lints", description: r##"unrecognized lint attribute"## },
360 Lint {
361 label: "unnameable_test_items",
362 description: r##"detects an item that cannot be named being marked as `#[test_case]`"##,
363 },
364 Lint { label: "unreachable_code", description: r##"detects unreachable code paths"## },
365 Lint { label: "unreachable_patterns", description: r##"detects unreachable patterns"## },
366 Lint {
367 label: "unreachable_pub",
368 description: r##"`pub` items not reachable from crate root"##,
369 },
370 Lint { label: "unsafe_code", description: r##"usage of `unsafe` code"## },
371 Lint {
372 label: "unsafe_op_in_unsafe_fn",
373 description: r##"unsafe operations in unsafe functions without an explicit unsafe block are deprecated"##,
374 },
375 Lint {
376 label: "unstable_features",
377 description: r##"enabling unstable features (deprecated. do not use)"##,
378 },
379 Lint {
380 label: "unstable_name_collisions",
381 description: r##"detects name collision with an existing but unstable method"##,
382 },
383 Lint {
384 label: "unsupported_naked_functions",
385 description: r##"unsupported naked function definitions"##,
386 },
387 Lint {
388 label: "unused",
389 description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons"##,
390 },
391 Lint {
392 label: "unused_allocation",
393 description: r##"detects unnecessary allocations that can be eliminated"##,
394 },
395 Lint {
396 label: "unused_assignments",
397 description: r##"detect assignments that will never be read"##,
398 },
399 Lint {
400 label: "unused_attributes",
401 description: r##"detects attributes that were not used by the compiler"##,
402 },
403 Lint { label: "unused_braces", description: r##"unnecessary braces around an expression"## },
404 Lint {
405 label: "unused_comparisons",
406 description: r##"comparisons made useless by limits of the types involved"##,
407 },
408 Lint {
409 label: "unused_crate_dependencies",
410 description: r##"crate dependencies that are never used"##,
411 },
412 Lint {
413 label: "unused_doc_comments",
414 description: r##"detects doc comments that aren't used by rustdoc"##,
415 },
416 Lint { label: "unused_extern_crates", description: r##"extern crates that are never used"## },
417 Lint {
418 label: "unused_features",
419 description: r##"unused features found in crate-level `#[feature]` directives"##,
420 },
421 Lint {
422 label: "unused_import_braces",
423 description: r##"unnecessary braces around an imported item"##,
424 },
425 Lint { label: "unused_imports", description: r##"imports that are never used"## },
426 Lint { label: "unused_labels", description: r##"detects labels that are never used"## },
427 Lint {
428 label: "unused_lifetimes",
429 description: r##"detects lifetime parameters that are never used"##,
430 },
431 Lint { label: "unused_macros", description: r##"detects macros that were not used"## },
432 Lint {
433 label: "unused_must_use",
434 description: r##"unused result of a type flagged as `#[must_use]`"##,
435 },
436 Lint {
437 label: "unused_mut",
438 description: r##"detect mut variables which don't need to be mutable"##,
439 },
440 Lint {
441 label: "unused_parens",
442 description: r##"`if`, `match`, `while` and `return` do not need parentheses"##,
443 },
444 Lint {
445 label: "unused_qualifications",
446 description: r##"detects unnecessarily qualified names"##,
447 },
448 Lint {
449 label: "unused_results",
450 description: r##"unused result of an expression in a statement"##,
451 },
452 Lint { label: "unused_unsafe", description: r##"unnecessary use of an `unsafe` block"## },
453 Lint {
454 label: "unused_variables",
455 description: r##"detect variables which are not used in any way"##,
456 },
457 Lint {
458 label: "useless_deprecated",
459 description: r##"detects deprecation attributes with no effect"##,
460 },
461 Lint {
462 label: "variant_size_differences",
463 description: r##"detects enums with widely varying variant sizes"##,
464 },
465 Lint {
466 label: "warnings",
467 description: r##"mass-change the level for lints which produce warnings"##,
468 },
469 Lint {
470 label: "warnings",
471 description: r##"lint group for: all lints that are set to issue warnings"##,
472 },
473 Lint {
474 label: "where_clauses_object_safety",
475 description: r##"checks the object safety of where clauses"##,
476 },
477 Lint {
478 label: "while_true",
479 description: r##"suggest using `loop { }` instead of `while true { }`"##,
480 },
481];
482
483pub const FEATURES: &[Lint] = &[
484 Lint {
485 label: "abi_c_cmse_nonsecure_call",
486 description: r##"# `abi_c_cmse_nonsecure_call`
487
488The tracking issue for this feature is: [#81391]
489
490[#81391]: https://github.com/rust-lang/rust/issues/81391
491
492------------------------
493
494The [TrustZone-M
495feature](https://developer.arm.com/documentation/100690/latest/) is available
496for targets with the Armv8-M architecture profile (`thumbv8m` in their target
497name).
498LLVM, the Rust compiler and the linker are providing
499[support](https://developer.arm.com/documentation/ecm0359818/latest/) for the
500TrustZone-M feature.
501
502One of the things provided, with this unstable feature, is the
503`C-cmse-nonsecure-call` function ABI. This ABI is used on function pointers to
504non-secure code to mark a non-secure function call (see [section
5055.5](https://developer.arm.com/documentation/ecm0359818/latest/) for details).
506
507With this ABI, the compiler will do the following to perform the call:
508* save registers needed after the call to Secure memory
509* clear all registers that might contain confidential information
510* clear the Least Significant Bit of the function address
511* branches using the BLXNS instruction
512
513To avoid using the non-secure stack, the compiler will constrain the number and
514type of parameters/return value.
515
516The `extern "C-cmse-nonsecure-call"` ABI is otherwise equivalent to the
517`extern "C"` ABI.
518
519<!-- NOTE(ignore) this example is specific to thumbv8m targets -->
520
521``` rust,ignore
522#![no_std]
523#![feature(abi_c_cmse_nonsecure_call)]
524
525#[no_mangle]
526pub fn call_nonsecure_function(addr: usize) -> u32 {
527 let non_secure_function =
528 unsafe { core::mem::transmute::<usize, extern "C-cmse-nonsecure-call" fn() -> u32>(addr) };
529 non_secure_function()
530}
531```
532
533``` text
534$ rustc --emit asm --crate-type lib --target thumbv8m.main-none-eabi function.rs
535
536call_nonsecure_function:
537 .fnstart
538 .save {r7, lr}
539 push {r7, lr}
540 .setfp r7, sp
541 mov r7, sp
542 .pad #16
543 sub sp, #16
544 str r0, [sp, #12]
545 ldr r0, [sp, #12]
546 str r0, [sp, #8]
547 b .LBB0_1
548.LBB0_1:
549 ldr r0, [sp, #8]
550 push.w {r4, r5, r6, r7, r8, r9, r10, r11}
551 bic r0, r0, #1
552 mov r1, r0
553 mov r2, r0
554 mov r3, r0
555 mov r4, r0
556 mov r5, r0
557 mov r6, r0
558 mov r7, r0
559 mov r8, r0
560 mov r9, r0
561 mov r10, r0
562 mov r11, r0
563 mov r12, r0
564 msr apsr_nzcvq, r0
565 blxns r0
566 pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
567 str r0, [sp, #4]
568 b .LBB0_2
569.LBB0_2:
570 ldr r0, [sp, #4]
571 add sp, #16
572 pop {r7, pc}
573```
574"##,
575 },
576 Lint {
577 label: "abi_msp430_interrupt",
578 description: r##"# `abi_msp430_interrupt`
579
580The tracking issue for this feature is: [#38487]
581
582[#38487]: https://github.com/rust-lang/rust/issues/38487
583
584------------------------
585
586In the MSP430 architecture, interrupt handlers have a special calling
587convention. You can use the `"msp430-interrupt"` ABI to make the compiler apply
588the right calling convention to the interrupt handlers you define.
589
590<!-- NOTE(ignore) this example is specific to the msp430 target -->
591
592``` rust,ignore
593#![feature(abi_msp430_interrupt)]
594#![no_std]
595
596// Place the interrupt handler at the appropriate memory address
597// (Alternatively, you can use `#[used]` and remove `pub` and `#[no_mangle]`)
598#[link_section = "__interrupt_vector_10"]
599#[no_mangle]
600pub static TIM0_VECTOR: extern "msp430-interrupt" fn() = tim0;
601
602// The interrupt handler
603extern "msp430-interrupt" fn tim0() {
604 // ..
605}
606```
607
608``` text
609$ msp430-elf-objdump -CD ./target/msp430/release/app
610Disassembly of section __interrupt_vector_10:
611
6120000fff2 <TIM0_VECTOR>:
613 fff2: 00 c0 interrupt service routine at 0xc000
614
615Disassembly of section .text:
616
6170000c000 <int::tim0>:
618 c000: 00 13 reti
619```
620"##,
621 },
622 Lint {
623 label: "abi_ptx",
624 description: r##"# `abi_ptx`
625
626The tracking issue for this feature is: [#38788]
627
628[#38788]: https://github.com/rust-lang/rust/issues/38788
629
630------------------------
631
632When emitting PTX code, all vanilla Rust functions (`fn`) get translated to
633"device" functions. These functions are *not* callable from the host via the
634CUDA API so a crate with only device functions is not too useful!
635
636OTOH, "global" functions *can* be called by the host; you can think of them
637as the real public API of your crate. To produce a global function use the
638`"ptx-kernel"` ABI.
639
640<!-- NOTE(ignore) this example is specific to the nvptx targets -->
641
642``` rust,ignore
643#![feature(abi_ptx)]
644#![no_std]
645
646pub unsafe extern "ptx-kernel" fn global_function() {
647 device_function();
648}
649
650pub fn device_function() {
651 // ..
652}
653```
654
655``` text
656$ xargo rustc --target nvptx64-nvidia-cuda --release -- --emit=asm
657
658$ cat $(find -name '*.s')
659//
660// Generated by LLVM NVPTX Back-End
661//
662
663.version 3.2
664.target sm_20
665.address_size 64
666
667 // .globl _ZN6kernel15global_function17h46111ebe6516b382E
668
669.visible .entry _ZN6kernel15global_function17h46111ebe6516b382E()
670{
671
672
673 ret;
674}
675
676 // .globl _ZN6kernel15device_function17hd6a0e4993bbf3f78E
677.visible .func _ZN6kernel15device_function17hd6a0e4993bbf3f78E()
678{
679
680
681 ret;
682}
683```
684"##,
685 },
686 Lint {
687 label: "abi_thiscall",
688 description: r##"# `abi_thiscall`
689
690The tracking issue for this feature is: [#42202]
691
692[#42202]: https://github.com/rust-lang/rust/issues/42202
693
694------------------------
695
696The MSVC ABI on x86 Windows uses the `thiscall` calling convention for C++
697instance methods by default; it is identical to the usual (C) calling
698convention on x86 Windows except that the first parameter of the method,
699the `this` pointer, is passed in the ECX register.
700"##,
701 },
702 Lint {
703 label: "allocator_api",
704 description: r##"# `allocator_api`
705
706The tracking issue for this feature is [#32838]
707
708[#32838]: https://github.com/rust-lang/rust/issues/32838
709
710------------------------
711
712Sometimes you want the memory for one collection to use a different
713allocator than the memory for another collection. In this case,
714replacing the global allocator is not a workable option. Instead,
715you need to pass in an instance of an `AllocRef` to each collection
716for which you want a custom allocator.
717
718TBD
719"##,
720 },
721 Lint {
722 label: "allocator_internals",
723 description: r##"# `allocator_internals`
724
725This feature does not have a tracking issue, it is an unstable implementation
726detail of the `global_allocator` feature not intended for use outside the
727compiler.
728
729------------------------
730"##,
731 },
732 Lint {
733 label: "arbitrary_enum_discriminant",
734 description: r##"# `arbitrary_enum_discriminant`
735
736The tracking issue for this feature is: [#60553]
737
738[#60553]: https://github.com/rust-lang/rust/issues/60553
739
740------------------------
741
742The `arbitrary_enum_discriminant` feature permits tuple-like and
743struct-like enum variants with `#[repr(<int-type>)]` to have explicit discriminants.
744
745## Examples
746
747```rust
748#![feature(arbitrary_enum_discriminant)]
749
750#[allow(dead_code)]
751#[repr(u8)]
752enum Enum {
753 Unit = 3,
754 Tuple(u16) = 2,
755 Struct {
756 a: u8,
757 b: u16,
758 } = 1,
759}
760
761impl Enum {
762 fn tag(&self) -> u8 {
763 unsafe { *(self as *const Self as *const u8) }
764 }
765}
766
767assert_eq!(3, Enum::Unit.tag());
768assert_eq!(2, Enum::Tuple(5).tag());
769assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag());
770```
771"##,
772 },
773 Lint {
774 label: "asm",
775 description: r##"# `asm`
776
777The tracking issue for this feature is: [#72016]
778
779[#72016]: https://github.com/rust-lang/rust/issues/72016
780
781------------------------
782
783For extremely low-level manipulations and performance reasons, one
784might wish to control the CPU directly. Rust supports using inline
785assembly to do this via the `asm!` macro.
786
787# Guide-level explanation
788[guide-level-explanation]: #guide-level-explanation
789
790Rust provides support for inline assembly via the `asm!` macro.
791It can be used to embed handwritten assembly in the assembly output generated by the compiler.
792Generally this should not be necessary, but might be where the required performance or timing
793cannot be otherwise achieved. Accessing low level hardware primitives, e.g. in kernel code, may also demand this functionality.
794
795> **Note**: the examples here are given in x86/x86-64 assembly, but other architectures are also supported.
796
797Inline assembly is currently supported on the following architectures:
798- x86 and x86-64
799- ARM
800- AArch64
801- RISC-V
802- NVPTX
803- PowerPC
804- Hexagon
805- MIPS32r2 and MIPS64r2
806- wasm32
807
808## Basic usage
809
810Let us start with the simplest possible example:
811
812```rust,allow_fail
813#![feature(asm)]
814unsafe {
815 asm!("nop");
816}
817```
818
819This will insert a NOP (no operation) instruction into the assembly generated by the compiler.
820Note that all `asm!` invocations have to be inside an `unsafe` block, as they could insert
821arbitrary instructions and break various invariants. The instructions to be inserted are listed
822in the first argument of the `asm!` macro as a string literal.
823
824## Inputs and outputs
825
826Now inserting an instruction that does nothing is rather boring. Let us do something that
827actually acts on data:
828
829```rust,allow_fail
830#![feature(asm)]
831let x: u64;
832unsafe {
833 asm!("mov {}, 5", out(reg) x);
834}
835assert_eq!(x, 5);
836```
837
838This will write the value `5` into the `u64` variable `x`.
839You can see that the string literal we use to specify instructions is actually a template string.
840It is governed by the same rules as Rust [format strings][format-syntax].
841The arguments that are inserted into the template however look a bit different then you may
842be familiar with. First we need to specify if the variable is an input or an output of the
843inline assembly. In this case it is an output. We declared this by writing `out`.
844We also need to specify in what kind of register the assembly expects the variable.
845In this case we put it in an arbitrary general purpose register by specifying `reg`.
846The compiler will choose an appropriate register to insert into
847the template and will read the variable from there after the inline assembly finishes executing.
848
849Let us see another example that also uses an input:
850
851```rust,allow_fail
852#![feature(asm)]
853let i: u64 = 3;
854let o: u64;
855unsafe {
856 asm!(
857 "mov {0}, {1}",
858 "add {0}, {number}",
859 out(reg) o,
860 in(reg) i,
861 number = const 5,
862 );
863}
864assert_eq!(o, 8);
865```
866
867This will add `5` to the input in variable `i` and write the result to variable `o`.
868The particular way this assembly does this is first copying the value from `i` to the output,
869and then adding `5` to it.
870
871The example shows a few things:
872
873First, we can see that `asm!` allows multiple template string arguments; each
874one is treated as a separate line of assembly code, as if they were all joined
875together with newlines between them. This makes it easy to format assembly
876code.
877
878Second, we can see that inputs are declared by writing `in` instead of `out`.
879
880Third, one of our operands has a type we haven't seen yet, `const`.
881This tells the compiler to expand this argument to value directly inside the assembly template.
882This is only possible for constants and literals.
883
884Fourth, we can see that we can specify an argument number, or name as in any format string.
885For inline assembly templates this is particularly useful as arguments are often used more than once.
886For more complex inline assembly using this facility is generally recommended, as it improves
887readability, and allows reordering instructions without changing the argument order.
888
889We can further refine the above example to avoid the `mov` instruction:
890
891```rust,allow_fail
892#![feature(asm)]
893let mut x: u64 = 3;
894unsafe {
895 asm!("add {0}, {number}", inout(reg) x, number = const 5);
896}
897assert_eq!(x, 8);
898```
899
900We can see that `inout` is used to specify an argument that is both input and output.
901This is different from specifying an input and output separately in that it is guaranteed to assign both to the same register.
902
903It is also possible to specify different variables for the input and output parts of an `inout` operand:
904
905```rust,allow_fail
906#![feature(asm)]
907let x: u64 = 3;
908let y: u64;
909unsafe {
910 asm!("add {0}, {number}", inout(reg) x => y, number = const 5);
911}
912assert_eq!(y, 8);
913```
914
915## Late output operands
916
917The Rust compiler is conservative with its allocation of operands. It is assumed that an `out`
918can be written at any time, and can therefore not share its location with any other argument.
919However, to guarantee optimal performance it is important to use as few registers as possible,
920so they won't have to be saved and reloaded around the inline assembly block.
921To achieve this Rust provides a `lateout` specifier. This can be used on any output that is
922written only after all inputs have been consumed.
923There is also a `inlateout` variant of this specifier.
924
925Here is an example where `inlateout` *cannot* be used:
926
927```rust,allow_fail
928#![feature(asm)]
929let mut a: u64 = 4;
930let b: u64 = 4;
931let c: u64 = 4;
932unsafe {
933 asm!(
934 "add {0}, {1}",
935 "add {0}, {2}",
936 inout(reg) a,
937 in(reg) b,
938 in(reg) c,
939 );
940}
941assert_eq!(a, 12);
942```
943
944Here the compiler is free to allocate the same register for inputs `b` and `c` since it knows they have the same value. However it must allocate a separate register for `a` since it uses `inout` and not `inlateout`. If `inlateout` was used, then `a` and `c` could be allocated to the same register, in which case the first instruction to overwrite the value of `c` and cause the assembly code to produce the wrong result.
945
946However the following example can use `inlateout` since the output is only modified after all input registers have been read:
947
948```rust,allow_fail
949#![feature(asm)]
950let mut a: u64 = 4;
951let b: u64 = 4;
952unsafe {
953 asm!("add {0}, {1}", inlateout(reg) a, in(reg) b);
954}
955assert_eq!(a, 8);
956```
957
958As you can see, this assembly fragment will still work correctly if `a` and `b` are assigned to the same register.
959
960## Explicit register operands
961
962Some instructions require that the operands be in a specific register.
963Therefore, Rust inline assembly provides some more specific constraint specifiers.
964While `reg` is generally available on any architecture, these are highly architecture specific. E.g. for x86 the general purpose registers `eax`, `ebx`, `ecx`, `edx`, `ebp`, `esi`, and `edi`
965among others can be addressed by their name.
966
967```rust,allow_fail,no_run
968#![feature(asm)]
969let cmd = 0xd1;
970unsafe {
971 asm!("out 0x64, eax", in("eax") cmd);
972}
973```
974
975In this example we call the `out` instruction to output the content of the `cmd` variable
976to port `0x64`. Since the `out` instruction only accepts `eax` (and its sub registers) as operand
977we had to use the `eax` constraint specifier.
978
979Note that unlike other operand types, explicit register operands cannot be used in the template string: you can't use `{}` and should write the register name directly instead. Also, they must appear at the end of the operand list after all other operand types.
980
981Consider this example which uses the x86 `mul` instruction:
982
983```rust,allow_fail
984#![feature(asm)]
985fn mul(a: u64, b: u64) -> u128 {
986 let lo: u64;
987 let hi: u64;
988
989 unsafe {
990 asm!(
991 // The x86 mul instruction takes rax as an implicit input and writes
992 // the 128-bit result of the multiplication to rax:rdx.
993 "mul {}",
994 in(reg) a,
995 inlateout("rax") b => lo,
996 lateout("rdx") hi
997 );
998 }
999
1000 ((hi as u128) << 64) + lo as u128
1001}
1002```
1003
1004This uses the `mul` instruction to multiply two 64-bit inputs with a 128-bit result.
1005The only explicit operand is a register, that we fill from the variable `a`.
1006The second operand is implicit, and must be the `rax` register, which we fill from the variable `b`.
1007The lower 64 bits of the result are stored in `rax` from which we fill the variable `lo`.
1008The higher 64 bits are stored in `rdx` from which we fill the variable `hi`.
1009
1010## Clobbered registers
1011
1012In many cases inline assembly will modify state that is not needed as an output.
1013Usually this is either because we have to use a scratch register in the assembly,
1014or instructions modify state that we don't need to further examine.
1015This state is generally referred to as being "clobbered".
1016We need to tell the compiler about this since it may need to save and restore this state
1017around the inline assembly block.
1018
1019```rust,allow_fail
1020#![feature(asm)]
1021let ebx: u32;
1022let ecx: u32;
1023
1024unsafe {
1025 asm!(
1026 "cpuid",
1027 // EAX 4 selects the "Deterministic Cache Parameters" CPUID leaf
1028 inout("eax") 4 => _,
1029 // ECX 0 selects the L0 cache information.
1030 inout("ecx") 0 => ecx,
1031 lateout("ebx") ebx,
1032 lateout("edx") _,
1033 );
1034}
1035
1036println!(
1037 "L1 Cache: {}",
1038 ((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1)
1039);
1040```
1041
1042In the example above we use the `cpuid` instruction to get the L1 cache size.
1043This instruction writes to `eax`, `ebx`, `ecx`, and `edx`, but for the cache size we only care about the contents of `ebx` and `ecx`.
1044
1045However we still need to tell the compiler that `eax` and `edx` have been modified so that it can save any values that were in these registers before the asm. This is done by declaring these as outputs but with `_` instead of a variable name, which indicates that the output value is to be discarded.
1046
1047This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code:
1048
1049```rust,allow_fail
1050#![feature(asm)]
1051// Multiply x by 6 using shifts and adds
1052let mut x: u64 = 4;
1053unsafe {
1054 asm!(
1055 "mov {tmp}, {x}",
1056 "shl {tmp}, 1",
1057 "shl {x}, 2",
1058 "add {x}, {tmp}",
1059 x = inout(reg) x,
1060 tmp = out(reg) _,
1061 );
1062}
1063assert_eq!(x, 4 * 6);
1064```
1065
1066## Symbol operands
1067
1068A special operand type, `sym`, allows you to use the symbol name of a `fn` or `static` in inline assembly code.
1069This allows you to call a function or access a global variable without needing to keep its address in a register.
1070
1071```rust,allow_fail
1072#![feature(asm)]
1073extern "C" fn foo(arg: i32) {
1074 println!("arg = {}", arg);
1075}
1076
1077fn call_foo(arg: i32) {
1078 unsafe {
1079 asm!(
1080 "call {}",
1081 sym foo,
1082 // 1st argument in rdi, which is caller-saved
1083 inout("rdi") arg => _,
1084 // All caller-saved registers must be marked as clobbered
1085 out("rax") _, out("rcx") _, out("rdx") _, out("rsi") _,
1086 out("r8") _, out("r9") _, out("r10") _, out("r11") _,
1087 out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _,
1088 out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _,
1089 out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,
1090 out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,
1091 // Also mark AVX-512 registers as clobbered. This is accepted by the
1092 // compiler even if AVX-512 is not enabled on the current target.
1093 out("xmm16") _, out("xmm17") _, out("xmm18") _, out("xmm19") _,
1094 out("xmm20") _, out("xmm21") _, out("xmm22") _, out("xmm23") _,
1095 out("xmm24") _, out("xmm25") _, out("xmm26") _, out("xmm27") _,
1096 out("xmm28") _, out("xmm29") _, out("xmm30") _, out("xmm31") _,
1097 )
1098 }
1099}
1100```
1101
1102Note that the `fn` or `static` item does not need to be public or `#[no_mangle]`:
1103the compiler will automatically insert the appropriate mangled symbol name into the assembly code.
1104
1105## Register template modifiers
1106
1107In some cases, fine control is needed over the way a register name is formatted when inserted into the template string. This is needed when an architecture's assembly language has several names for the same register, each typically being a "view" over a subset of the register (e.g. the low 32 bits of a 64-bit register).
1108
1109By default the compiler will always choose the name that refers to the full register size (e.g. `rax` on x86-64, `eax` on x86, etc).
1110
1111This default can be overriden by using modifiers on the template string operands, just like you would with format strings:
1112
1113```rust,allow_fail
1114#![feature(asm)]
1115let mut x: u16 = 0xab;
1116
1117unsafe {
1118 asm!("mov {0:h}, {0:l}", inout(reg_abcd) x);
1119}
1120
1121assert_eq!(x, 0xabab);
1122```
1123
1124In this example, we use the `reg_abcd` register class to restrict the register allocator to the 4 legacy x86 register (`ax`, `bx`, `cx`, `dx`) of which the first two bytes can be addressed independently.
1125
1126Let us assume that the register allocator has chosen to allocate `x` in the `ax` register.
1127The `h` modifier will emit the register name for the high byte of that register and the `l` modifier will emit the register name for the low byte. The asm code will therefore be expanded as `mov ah, al` which copies the low byte of the value into the high byte.
1128
1129If you use a smaller data type (e.g. `u16`) with an operand and forget the use template modifiers, the compiler will emit a warning and suggest the correct modifier to use.
1130
1131## Memory address operands
1132
1133Sometimes assembly instructions require operands passed via memory addresses/memory locations.
1134You have to manually use the memory address syntax specified by the respectively architectures.
1135For example, in x86/x86_64 and intel assembly syntax, you should wrap inputs/outputs in `[]`
1136to indicate they are memory operands:
1137
1138```rust,allow_fail
1139#![feature(asm, llvm_asm)]
1140# fn load_fpu_control_word(control: u16) {
1141unsafe {
1142 asm!("fldcw [{}]", in(reg) &control, options(nostack));
1143
1144 // Previously this would have been written with the deprecated `llvm_asm!` like this
1145 llvm_asm!("fldcw $0" :: "m" (control) :: "volatile");
1146}
1147# }
1148```
1149
1150## Labels
1151
1152The compiler is allowed to instantiate multiple copies an `asm!` block, for example when the function containing it is inlined in multiple places. As a consequence, you should only use GNU assembler [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions.
1153
1154Moreover, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values.
1155
1156```rust,allow_fail
1157#![feature(asm)]
1158
1159let mut a = 0;
1160unsafe {
1161 asm!(
1162 "mov {0}, 10",
1163 "2:",
1164 "sub {0}, 1",
1165 "cmp {0}, 3",
1166 "jle 2f",
1167 "jmp 2b",
1168 "2:",
1169 "add {0}, 2",
1170 out(reg) a
1171 );
1172}
1173assert_eq!(a, 5);
1174```
1175
1176This will decrement the `{0}` register value from 10 to 3, then add 2 and store it in `a`.
1177
1178This example show a few thing:
1179
1180First that the same number can be used as a label multiple times in the same inline block.
1181
1182Second, that when a numeric label is used as a reference (as an instruction operand, for example), the suffixes b (“backward”) or f (“forward”) should be added to the numeric label. It will then refer to the nearest label defined by this number in this direction.
1183
1184[local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
1185[an llvm bug]: https://bugs.llvm.org/show_bug.cgi?id=36144
1186
1187## Options
1188
1189By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However in many cases, it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.
1190
1191Let's take our previous example of an `add` instruction:
1192
1193```rust,allow_fail
1194#![feature(asm)]
1195let mut a: u64 = 4;
1196let b: u64 = 4;
1197unsafe {
1198 asm!(
1199 "add {0}, {1}",
1200 inlateout(reg) a, in(reg) b,
1201 options(pure, nomem, nostack),
1202 );
1203}
1204assert_eq!(a, 8);
1205```
1206
1207Options can be provided as an optional final argument to the `asm!` macro. We specified three options here:
1208- `pure` means that the asm code has no observable side effects and that its output depends only on its inputs. This allows the compiler optimizer to call the inline asm fewer times or even eliminate it entirely.
1209- `nomem` means that the asm code does not read or write to memory. By default the compiler will assume that inline assembly can read or write any memory address that is accessible to it (e.g. through a pointer passed as an operand, or a global).
1210- `nostack` means that the asm code does not push any data onto the stack. This allows the compiler to use optimizations such as the stack red zone on x86-64 to avoid stack pointer adjustments.
1211
1212These allow the compiler to better optimize code using `asm!`, for example by eliminating pure `asm!` blocks whose outputs are not needed.
1213
1214See the reference for the full list of available options and their effects.
1215
1216# Reference-level explanation
1217[reference-level-explanation]: #reference-level-explanation
1218
1219Inline assembler is implemented as an unsafe macro `asm!()`.
1220The first argument to this macro is a template string literal used to build the final assembly.
1221The following arguments specify input and output operands.
1222When required, options are specified as the final argument.
1223
1224The following ABNF specifies the general syntax:
1225
1226```text
1227dir_spec := "in" / "out" / "lateout" / "inout" / "inlateout"
1228reg_spec := <register class> / "<explicit register>"
1229operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_"
1230reg_operand := dir_spec "(" reg_spec ")" operand_expr
1231operand := reg_operand / "const" const_expr / "sym" path
1232option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax"
1233options := "options(" option *["," option] [","] ")"
1234asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," options] [","] ")"
1235```
1236
1237The macro will initially be supported only on ARM, AArch64, Hexagon, PowerPC, x86, x86-64 and RISC-V targets. Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target.
1238
1239[format-syntax]: https://doc.rust-lang.org/std/fmt/#syntax
1240
1241## Template string arguments
1242
1243The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported.
1244
1245An `asm!` invocation may have one or more template string arguments; an `asm!` with multiple template string arguments is treated as if all the strings were concatenated with a `\n` between them. The expected usage is for each template string argument to correspond to a line of assembly code. All template string arguments must appear before any other arguments.
1246
1247As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after named arguments if any.
1248
1249Explicit register operands cannot be used by placeholders in the template string. All other named and positional operands must appear at least once in the template string, otherwise a compiler error is generated.
1250
1251The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler.
1252
1253The 5 targets specified in this RFC (x86, ARM, AArch64, RISC-V, Hexagon) all use the assembly code syntax of the GNU assembler (GAS). On x86, the `.intel_syntax noprefix` mode of GAS is used by default. On ARM, the `.syntax unified` mode is used. These targets impose an additional restriction on the assembly code: any assembler state (e.g. the current section which can be changed with `.section`) must be restored to its original value at the end of the asm string. Assembly code that does not conform to the GAS syntax will result in assembler-specific behavior.
1254
1255[rfc-2795]: https://github.com/rust-lang/rfcs/pull/2795
1256
1257## Operand type
1258
1259Several types of operands are supported:
1260
1261* `in(<reg>) <expr>`
1262 - `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.
1263 - The allocated register will contain the value of `<expr>` at the start of the asm code.
1264 - The allocated register must contain the same value at the end of the asm code (except if a `lateout` is allocated to the same register).
1265* `out(<reg>) <expr>`
1266 - `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.
1267 - The allocated register will contain an undefined value at the start of the asm code.
1268 - `<expr>` must be a (possibly uninitialized) place expression, to which the contents of the allocated register is written to at the end of the asm code.
1269 - An underscore (`_`) may be specified instead of an expression, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber).
1270* `lateout(<reg>) <expr>`
1271 - Identical to `out` except that the register allocator can reuse a register allocated to an `in`.
1272 - You should only write to the register after all inputs are read, otherwise you may clobber an input.
1273* `inout(<reg>) <expr>`
1274 - `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.
1275 - The allocated register will contain the value of `<expr>` at the start of the asm code.
1276 - `<expr>` must be a mutable initialized place expression, to which the contents of the allocated register is written to at the end of the asm code.
1277* `inout(<reg>) <in expr> => <out expr>`
1278 - Same as `inout` except that the initial value of the register is taken from the value of `<in expr>`.
1279 - `<out expr>` must be a (possibly uninitialized) place expression, to which the contents of the allocated register is written to at the end of the asm code.
1280 - An underscore (`_`) may be specified instead of an expression for `<out expr>`, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber).
1281 - `<in expr>` and `<out expr>` may have different types.
1282* `inlateout(<reg>) <expr>` / `inlateout(<reg>) <in expr> => <out expr>`
1283 - Identical to `inout` except that the register allocator can reuse a register allocated to an `in` (this can happen if the compiler knows the `in` has the same initial value as the `inlateout`).
1284 - You should only write to the register after all inputs are read, otherwise you may clobber an input.
1285* `const <expr>`
1286 - `<expr>` must be an integer constant expression.
1287 - The value of the expression is formatted as a string and substituted directly into the asm template string.
1288* `sym <path>`
1289 - `<path>` must refer to a `fn` or `static`.
1290 - A mangled symbol name referring to the item is substituted into the asm template string.
1291 - The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc).
1292 - `<path>` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data.
1293
1294Operand expressions are evaluated from left to right, just like function call arguments. After the `asm!` has executed, outputs are written to in left to right order. This is significant if two outputs point to the same place: that place will contain the value of the rightmost output.
1295
1296## Register operands
1297
1298Input and output operands can be specified either as an explicit register or as a register class from which the register allocator can select a register. Explicit registers are specified as string literals (e.g. `"eax"`) while register classes are specified as identifiers (e.g. `reg`). Using string literals for register names enables support for architectures that use special characters in register names, such as MIPS (`$0`, `$1`, etc).
1299
1300Note that explicit registers treat register aliases (e.g. `r14` vs `lr` on ARM) and smaller views of a register (e.g. `eax` vs `rax`) as equivalent to the base register. It is a compile-time error to use the same explicit register for two input operands or two output operands. Additionally, it is also a compile-time error to use overlapping registers (e.g. ARM VFP) in input operands or in output operands.
1301
1302Only the following types are allowed as operands for inline assembly:
1303- Integers (signed and unsigned)
1304- Floating-point numbers
1305- Pointers (thin only)
1306- Function pointers
1307- SIMD vectors (structs defined with `#[repr(simd)]` and which implement `Copy`). This includes architecture-specific vector types defined in `std::arch` such as `__m128` (x86) or `int8x16_t` (ARM).
1308
1309Here is the list of currently supported register classes:
1310
1311| Architecture | Register class | Registers | LLVM constraint code |
1312| ------------ | -------------- | --------- | -------------------- |
1313| x86 | `reg` | `ax`, `bx`, `cx`, `dx`, `si`, `di`, `bp`, `r[8-15]` (x86-64 only) | `r` |
1314| x86 | `reg_abcd` | `ax`, `bx`, `cx`, `dx` | `Q` |
1315| x86-32 | `reg_byte` | `al`, `bl`, `cl`, `dl`, `ah`, `bh`, `ch`, `dh` | `q` |
1316| x86-64 | `reg_byte`\* | `al`, `bl`, `cl`, `dl`, `sil`, `dil`, `bpl`, `r[8-15]b` | `q` |
1317| x86 | `xmm_reg` | `xmm[0-7]` (x86) `xmm[0-15]` (x86-64) | `x` |
1318| x86 | `ymm_reg` | `ymm[0-7]` (x86) `ymm[0-15]` (x86-64) | `x` |
1319| x86 | `zmm_reg` | `zmm[0-7]` (x86) `zmm[0-31]` (x86-64) | `v` |
1320| x86 | `kreg` | `k[1-7]` | `Yk` |
1321| AArch64 | `reg` | `x[0-30]` | `r` |
1322| AArch64 | `vreg` | `v[0-31]` | `w` |
1323| AArch64 | `vreg_low16` | `v[0-15]` | `x` |
1324| ARM | `reg` | `r[0-12]`, `r14` | `r` |
1325| ARM (Thumb) | `reg_thumb` | `r[0-r7]` | `l` |
1326| ARM (ARM) | `reg_thumb` | `r[0-r12]`, `r14` | `l` |
1327| ARM | `sreg` | `s[0-31]` | `t` |
1328| ARM | `sreg_low16` | `s[0-15]` | `x` |
1329| ARM | `dreg` | `d[0-31]` | `w` |
1330| ARM | `dreg_low16` | `d[0-15]` | `t` |
1331| ARM | `dreg_low8` | `d[0-8]` | `x` |
1332| ARM | `qreg` | `q[0-15]` | `w` |
1333| ARM | `qreg_low8` | `q[0-7]` | `t` |
1334| ARM | `qreg_low4` | `q[0-3]` | `x` |
1335| MIPS | `reg` | `$[2-25]` | `r` |
1336| MIPS | `freg` | `$f[0-31]` | `f` |
1337| NVPTX | `reg16` | None\* | `h` |
1338| NVPTX | `reg32` | None\* | `r` |
1339| NVPTX | `reg64` | None\* | `l` |
1340| RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` |
1341| RISC-V | `freg` | `f[0-31]` | `f` |
1342| Hexagon | `reg` | `r[0-28]` | `r` |
1343| PowerPC | `reg` | `r[0-31]` | `r` |
1344| PowerPC | `reg_nonzero` | | `r[1-31]` | `b` |
1345| PowerPC | `freg` | `f[0-31]` | `f` |
1346| wasm32 | `local` | None\* | `r` |
1347
1348> **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register.
1349>
1350> Note #2: On x86-64 the high byte registers (e.g. `ah`) are not available in the `reg_byte` register class.
1351>
1352> Note #3: NVPTX doesn't have a fixed register set, so named registers are not supported.
1353>
1354> Note #4: WebAssembly doesn't have registers, so named registers are not supported.
1355
1356Additional register classes may be added in the future based on demand (e.g. MMX, x87, etc).
1357
1358Each register class has constraints on which value types they can be used with. This is necessary because the way a value is loaded into a register depends on its type. For example, on big-endian systems, loading a `i32x4` and a `i8x16` into a SIMD register may result in different register contents even if the byte-wise memory representation of both values is identical. The availability of supported types for a particular register class may depend on what target features are currently enabled.
1359
1360| Architecture | Register class | Target feature | Allowed types |
1361| ------------ | -------------- | -------------- | ------------- |
1362| x86-32 | `reg` | None | `i16`, `i32`, `f32` |
1363| x86-64 | `reg` | None | `i16`, `i32`, `f32`, `i64`, `f64` |
1364| x86 | `reg_byte` | None | `i8` |
1365| x86 | `xmm_reg` | `sse` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
1366| x86 | `ymm_reg` | `avx` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` <br> `i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` |
1367| x86 | `zmm_reg` | `avx512f` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` <br> `i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` <br> `i8x64`, `i16x32`, `i32x16`, `i64x8`, `f32x16`, `f64x8` |
1368| x86 | `kreg` | `axv512f` | `i8`, `i16` |
1369| x86 | `kreg` | `axv512bw` | `i32`, `i64` |
1370| AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
1371| AArch64 | `vreg` | `fp` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
1372| ARM | `reg` | None | `i8`, `i16`, `i32`, `f32` |
1373| ARM | `sreg` | `vfp2` | `i32`, `f32` |
1374| ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` |
1375| ARM | `qreg` | `neon` | `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4` |
1376| MIPS32 | `reg` | None | `i8`, `i16`, `i32`, `f32` |
1377| MIPS32 | `freg` | None | `f32`, `f64` |
1378| MIPS64 | `reg` | None | `i8`, `i16`, `i32`, `i64`, `f32`, `f64` |
1379| MIPS64 | `freg` | None | `f32`, `f64` |
1380| NVPTX | `reg16` | None | `i8`, `i16` |
1381| NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` |
1382| NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
1383| RISC-V32 | `reg` | None | `i8`, `i16`, `i32`, `f32` |
1384| RISC-V64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
1385| RISC-V | `freg` | `f` | `f32` |
1386| RISC-V | `freg` | `d` | `f64` |
1387| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` |
1388| PowerPC | `reg` | None | `i8`, `i16`, `i32` |
1389| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
1390| PowerPC | `freg` | None | `f32`, `f64` |
1391| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
1392
1393> **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target).
1394
1395If a value is of a smaller size than the register it is allocated in then the upper bits of that register will have an undefined value for inputs and will be ignored for outputs. The only exception is the `freg` register class on RISC-V where `f32` values are NaN-boxed in a `f64` as required by the RISC-V architecture.
1396
1397When separate input and output expressions are specified for an `inout` operand, both expressions must have the same type. The only exception is if both operands are pointers or integers, in which case they are only required to have the same size. This restriction exists because the register allocators in LLVM and GCC sometimes cannot handle tied operands with different types.
1398
1399## Register names
1400
1401Some registers have multiple names. These are all treated by the compiler as identical to the base register name. Here is the list of all supported register aliases:
1402
1403| Architecture | Base register | Aliases |
1404| ------------ | ------------- | ------- |
1405| x86 | `ax` | `eax`, `rax` |
1406| x86 | `bx` | `ebx`, `rbx` |
1407| x86 | `cx` | `ecx`, `rcx` |
1408| x86 | `dx` | `edx`, `rdx` |
1409| x86 | `si` | `esi`, `rsi` |
1410| x86 | `di` | `edi`, `rdi` |
1411| x86 | `bp` | `bpl`, `ebp`, `rbp` |
1412| x86 | `sp` | `spl`, `esp`, `rsp` |
1413| x86 | `ip` | `eip`, `rip` |
1414| x86 | `st(0)` | `st` |
1415| x86 | `r[8-15]` | `r[8-15]b`, `r[8-15]w`, `r[8-15]d` |
1416| x86 | `xmm[0-31]` | `ymm[0-31]`, `zmm[0-31]` |
1417| AArch64 | `x[0-30]` | `w[0-30]` |
1418| AArch64 | `x29` | `fp` |
1419| AArch64 | `x30` | `lr` |
1420| AArch64 | `sp` | `wsp` |
1421| AArch64 | `xzr` | `wzr` |
1422| AArch64 | `v[0-31]` | `b[0-31]`, `h[0-31]`, `s[0-31]`, `d[0-31]`, `q[0-31]` |
1423| ARM | `r[0-3]` | `a[1-4]` |
1424| ARM | `r[4-9]` | `v[1-6]` |
1425| ARM | `r9` | `rfp` |
1426| ARM | `r10` | `sl` |
1427| ARM | `r11` | `fp` |
1428| ARM | `r12` | `ip` |
1429| ARM | `r13` | `sp` |
1430| ARM | `r14` | `lr` |
1431| ARM | `r15` | `pc` |
1432| RISC-V | `x0` | `zero` |
1433| RISC-V | `x1` | `ra` |
1434| RISC-V | `x2` | `sp` |
1435| RISC-V | `x3` | `gp` |
1436| RISC-V | `x4` | `tp` |
1437| RISC-V | `x[5-7]` | `t[0-2]` |
1438| RISC-V | `x8` | `fp`, `s0` |
1439| RISC-V | `x9` | `s1` |
1440| RISC-V | `x[10-17]` | `a[0-7]` |
1441| RISC-V | `x[18-27]` | `s[2-11]` |
1442| RISC-V | `x[28-31]` | `t[3-6]` |
1443| RISC-V | `f[0-7]` | `ft[0-7]` |
1444| RISC-V | `f[8-9]` | `fs[0-1]` |
1445| RISC-V | `f[10-17]` | `fa[0-7]` |
1446| RISC-V | `f[18-27]` | `fs[2-11]` |
1447| RISC-V | `f[28-31]` | `ft[8-11]` |
1448| Hexagon | `r29` | `sp` |
1449| Hexagon | `r30` | `fr` |
1450| Hexagon | `r31` | `lr` |
1451
1452Some registers cannot be used for input or output operands:
1453
1454| Architecture | Unsupported register | Reason |
1455| ------------ | -------------------- | ------ |
1456| All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. |
1457| All | `bp` (x86), `x29` (AArch64), `x8` (RISC-V), `fr` (Hexagon), `$fp` (MIPS) | The frame pointer cannot be used as an input or output. |
1458| ARM | `r7` or `r11` | On ARM the frame pointer can be either `r7` or `r11` depending on the target. The frame pointer cannot be used as an input or output. |
1459| All | `si` (x86-32), `bx` (x86-64), `r6` (ARM), `x19` (AArch64), `r19` (Hexagon), `x9` (RISC-V) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. |
1460| x86 | `k0` | This is a constant zero register which can't be modified. |
1461| x86 | `ip` | This is the program counter, not a real register. |
1462| x86 | `mm[0-7]` | MMX registers are not currently supported (but may be in the future). |
1463| x86 | `st([0-7])` | x87 registers are not currently supported (but may be in the future). |
1464| AArch64 | `xzr` | This is a constant zero register which can't be modified. |
1465| ARM | `pc` | This is the program counter, not a real register. |
1466| ARM | `r9` | This is a reserved register on some ARM targets. |
1467| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
1468| MIPS | `$1` or `$at` | Reserved for assembler. |
1469| MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. |
1470| MIPS | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. |
1471| MIPS | `$ra` | Return address cannot be used as inputs or outputs. |
1472| RISC-V | `x0` | This is a constant zero register which can't be modified. |
1473| RISC-V | `gp`, `tp` | These registers are reserved and cannot be used as inputs or outputs. |
1474| Hexagon | `lr` | This is the link register which cannot be used as an input or output. |
1475
1476In some cases LLVM will allocate a "reserved register" for `reg` operands even though this register cannot be explicitly specified. Assembly code making use of reserved registers should be careful since `reg` operands may alias with those registers. Reserved registers are the frame pointer and base pointer
1477- The frame pointer and LLVM base pointer on all architectures.
1478- `r9` on ARM.
1479- `x18` on AArch64.
1480
1481## Template modifiers
1482
1483The placeholders can be augmented by modifiers which are specified after the `:` in the curly braces. These modifiers do not affect register allocation, but change the way operands are formatted when inserted into the template string. Only one modifier is allowed per template placeholder.
1484
1485The supported modifiers are a subset of LLVM's (and GCC's) [asm template argument modifiers][llvm-argmod], but do not use the same letter codes.
1486
1487| Architecture | Register class | Modifier | Example output | LLVM modifier |
1488| ------------ | -------------- | -------- | -------------- | ------------- |
1489| x86-32 | `reg` | None | `eax` | `k` |
1490| x86-64 | `reg` | None | `rax` | `q` |
1491| x86-32 | `reg_abcd` | `l` | `al` | `b` |
1492| x86-64 | `reg` | `l` | `al` | `b` |
1493| x86 | `reg_abcd` | `h` | `ah` | `h` |
1494| x86 | `reg` | `x` | `ax` | `w` |
1495| x86 | `reg` | `e` | `eax` | `k` |
1496| x86-64 | `reg` | `r` | `rax` | `q` |
1497| x86 | `reg_byte` | None | `al` / `ah` | None |
1498| x86 | `xmm_reg` | None | `xmm0` | `x` |
1499| x86 | `ymm_reg` | None | `ymm0` | `t` |
1500| x86 | `zmm_reg` | None | `zmm0` | `g` |
1501| x86 | `*mm_reg` | `x` | `xmm0` | `x` |
1502| x86 | `*mm_reg` | `y` | `ymm0` | `t` |
1503| x86 | `*mm_reg` | `z` | `zmm0` | `g` |
1504| x86 | `kreg` | None | `k1` | None |
1505| AArch64 | `reg` | None | `x0` | `x` |
1506| AArch64 | `reg` | `w` | `w0` | `w` |
1507| AArch64 | `reg` | `x` | `x0` | `x` |
1508| AArch64 | `vreg` | None | `v0` | None |
1509| AArch64 | `vreg` | `v` | `v0` | None |
1510| AArch64 | `vreg` | `b` | `b0` | `b` |
1511| AArch64 | `vreg` | `h` | `h0` | `h` |
1512| AArch64 | `vreg` | `s` | `s0` | `s` |
1513| AArch64 | `vreg` | `d` | `d0` | `d` |
1514| AArch64 | `vreg` | `q` | `q0` | `q` |
1515| ARM | `reg` | None | `r0` | None |
1516| ARM | `sreg` | None | `s0` | None |
1517| ARM | `dreg` | None | `d0` | `P` |
1518| ARM | `qreg` | None | `q0` | `q` |
1519| ARM | `qreg` | `e` / `f` | `d0` / `d1` | `e` / `f` |
1520| MIPS | `reg` | None | `$2` | None |
1521| MIPS | `freg` | None | `$f0` | None |
1522| NVPTX | `reg16` | None | `rs0` | None |
1523| NVPTX | `reg32` | None | `r0` | None |
1524| NVPTX | `reg64` | None | `rd0` | None |
1525| RISC-V | `reg` | None | `x1` | None |
1526| RISC-V | `freg` | None | `f0` | None |
1527| Hexagon | `reg` | None | `r0` | None |
1528| PowerPC | `reg` | None | `0` | None |
1529| PowerPC | `reg_nonzero` | None | `3` | `b` |
1530| PowerPC | `freg` | None | `0` | None |
1531
1532> Notes:
1533> - on ARM `e` / `f`: this prints the low or high doubleword register name of a NEON quad (128-bit) register.
1534> - on x86: our behavior for `reg` with no modifiers differs from what GCC does. GCC will infer the modifier based on the operand value type, while we default to the full register size.
1535> - on x86 `xmm_reg`: the `x`, `t` and `g` LLVM modifiers are not yet implemented in LLVM (they are supported by GCC only), but this should be a simple change.
1536
1537As stated in the previous section, passing an input value smaller than the register width will result in the upper bits of the register containing undefined values. This is not a problem if the inline asm only accesses the lower bits of the register, which can be done by using a template modifier to use a subregister name in the asm code (e.g. `ax` instead of `rax`). Since this an easy pitfall, the compiler will suggest a template modifier to use where appropriate given the input type. If all references to an operand already have modifiers then the warning is suppressed for that operand.
1538
1539[llvm-argmod]: http://llvm.org/docs/LangRef.html#asm-template-argument-modifiers
1540
1541## Options
1542
1543Flags are used to further influence the behavior of the inline assembly block.
1544Currently the following options are defined:
1545- `pure`: The `asm` block has no side effects, and its outputs depend only on its direct inputs (i.e. the values themselves, not what they point to) or values read from memory (unless the `nomem` options is also set). This allows the compiler to execute the `asm` block fewer times than specified in the program (e.g. by hoisting it out of a loop) or even eliminate it entirely if the outputs are not used.
1546- `nomem`: The `asm` blocks does not read or write to any memory. This allows the compiler to cache the values of modified global variables in registers across the `asm` block since it knows that they are not read or written to by the `asm`.
1547- `readonly`: The `asm` block does not write to any memory. This allows the compiler to cache the values of unmodified global variables in registers across the `asm` block since it knows that they are not written to by the `asm`.
1548- `preserves_flags`: The `asm` block does not modify the flags register (defined in the rules below). This allows the compiler to avoid recomputing the condition flags after the `asm` block.
1549- `noreturn`: The `asm` block never returns, and its return type is defined as `!` (never). Behavior is undefined if execution falls through past the end of the asm code. A `noreturn` asm block behaves just like a function which doesn't return; notably, local variables in scope are not dropped before it is invoked.
1550- `nostack`: The `asm` block does not push data to the stack, or write to the stack red-zone (if supported by the target). If this option is *not* used then the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call.
1551- `att_syntax`: This option is only valid on x86, and causes the assembler to use the `.att_syntax prefix` mode of the GNU assembler. Register operands are substituted in with a leading `%`.
1552
1553The compiler performs some additional checks on options:
1554- The `nomem` and `readonly` options are mutually exclusive: it is a compile-time error to specify both.
1555- The `pure` option must be combined with either the `nomem` or `readonly` options, otherwise a compile-time error is emitted.
1556- It is a compile-time error to specify `pure` on an asm block with no outputs or only discarded outputs (`_`).
1557- It is a compile-time error to specify `noreturn` on an asm block with outputs.
1558
1559## Rules for inline assembly
1560
1561- Any registers not specified as inputs will contain an undefined value on entry to the asm block.
1562 - An "undefined value" in the context of inline assembly means that the register can (non-deterministically) have any one of the possible values allowed by the architecture. Notably it is not the same as an LLVM `undef` which can have a different value every time you read it (since such a concept does not exist in assembly code).
1563- Any registers not specified as outputs must have the same value upon exiting the asm block as they had on entry, otherwise behavior is undefined.
1564 - This only applies to registers which can be specified as an input or output. Other registers follow target-specific rules.
1565 - Note that a `lateout` may be allocated to the same register as an `in`, in which case this rule does not apply. Code should not rely on this however since it depends on the results of register allocation.
1566- Behavior is undefined if execution unwinds out of an asm block.
1567 - This also applies if the assembly code calls a function which then unwinds.
1568- The set of memory locations that assembly code is allowed the read and write are the same as those allowed for an FFI function.
1569 - Refer to the unsafe code guidelines for the exact rules.
1570 - If the `readonly` option is set, then only memory reads are allowed.
1571 - If the `nomem` option is set then no reads or writes to memory are allowed.
1572 - These rules do not apply to memory which is private to the asm code, such as stack space allocated within the asm block.
1573- The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed.
1574 - This effectively means that the compiler must treat the `asm!` as a black box and only take the interface specification into account, not the instructions themselves.
1575 - Runtime code patching is allowed, via target-specific mechanisms (outside the scope of this RFC).
1576- Unless the `nostack` option is set, asm code is allowed to use stack space below the stack pointer.
1577 - On entry to the asm block the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call.
1578 - You are responsible for making sure you don't overflow the stack (e.g. use stack probing to ensure you hit a guard page).
1579 - You should adjust the stack pointer when allocating stack memory as required by the target ABI.
1580 - The stack pointer must be restored to its original value before leaving the asm block.
1581- If the `noreturn` option is set then behavior is undefined if execution falls through to the end of the asm block.
1582- If the `pure` option is set then behavior is undefined if the `asm` has side-effects other than its direct outputs. Behavior is also undefined if two executions of the `asm` code with the same inputs result in different outputs.
1583 - When used with the `nomem` option, "inputs" are just the direct inputs of the `asm!`.
1584 - When used with the `readonly` option, "inputs" comprise the direct inputs of the `asm!` and any memory that the `asm!` block is allowed to read.
1585- These flags registers must be restored upon exiting the asm block if the `preserves_flags` option is set:
1586 - x86
1587 - Status flags in `EFLAGS` (CF, PF, AF, ZF, SF, OF).
1588 - Floating-point status word (all).
1589 - Floating-point exception flags in `MXCSR` (PE, UE, OE, ZE, DE, IE).
1590 - ARM
1591 - Condition flags in `CPSR` (N, Z, C, V)
1592 - Saturation flag in `CPSR` (Q)
1593 - Greater than or equal flags in `CPSR` (GE).
1594 - Condition flags in `FPSCR` (N, Z, C, V)
1595 - Saturation flag in `FPSCR` (QC)
1596 - Floating-point exception flags in `FPSCR` (IDC, IXC, UFC, OFC, DZC, IOC).
1597 - AArch64
1598 - Condition flags (`NZCV` register).
1599 - Floating-point status (`FPSR` register).
1600 - RISC-V
1601 - Floating-point exception flags in `fcsr` (`fflags`).
1602- On x86, the direction flag (DF in `EFLAGS`) is clear on entry to an asm block and must be clear on exit.
1603 - Behavior is undefined if the direction flag is set on exiting an asm block.
1604- The requirement of restoring the stack pointer and non-output registers to their original value only applies when exiting an `asm!` block.
1605 - This means that `asm!` blocks that never return (even if not marked `noreturn`) don't need to preserve these registers.
1606 - When returning to a different `asm!` block than you entered (e.g. for context switching), these registers must contain the value they had upon entering the `asm!` block that you are *exiting*.
1607 - You cannot exit an `asm!` block that has not been entered. Neither can you exit an `asm!` block that has already been exited.
1608 - You are responsible for switching any target-specific state (e.g. thread-local storage, stack bounds).
1609 - The set of memory locations that you may access is the intersection of those allowed by the `asm!` blocks you entered and exited.
1610- You cannot assume that an `asm!` block will appear exactly once in the output binary. The compiler is allowed to instantiate multiple copies of the `asm!` block, for example when the function containing it is inlined in multiple places.
1611
1612> **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call.
1613"##,
1614 },
1615 Lint {
1616 label: "auto_traits",
1617 description: r##"# `auto_traits`
1618
1619The tracking issue for this feature is [#13231]
1620
1621[#13231]: https://github.com/rust-lang/rust/issues/13231
1622
1623----
1624
1625The `auto_traits` feature gate allows you to define auto traits.
1626
1627Auto traits, like [`Send`] or [`Sync`] in the standard library, are marker traits
1628that are automatically implemented for every type, unless the type, or a type it contains,
1629has explicitly opted out via a negative impl. (Negative impls are separately controlled
1630by the `negative_impls` feature.)
1631
1632[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
1633[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
1634
1635```rust,ignore (partial-example)
1636impl !Trait for Type {}
1637```
1638
1639Example:
1640
1641```rust
1642#![feature(negative_impls)]
1643#![feature(auto_traits)]
1644
1645auto trait Valid {}
1646
1647struct True;
1648struct False;
1649
1650impl !Valid for False {}
1651
1652struct MaybeValid<T>(T);
1653
1654fn must_be_valid<T: Valid>(_t: T) { }
1655
1656fn main() {
1657 // works
1658 must_be_valid( MaybeValid(True) );
1659
1660 // compiler error - trait bound not satisfied
1661 // must_be_valid( MaybeValid(False) );
1662}
1663```
1664
1665## Automatic trait implementations
1666
1667When a type is declared as an `auto trait`, we will automatically
1668create impls for every struct/enum/union, unless an explicit impl is
1669provided. These automatic impls contain a where clause for each field
1670of the form `T: AutoTrait`, where `T` is the type of the field and
1671`AutoTrait` is the auto trait in question. As an example, consider the
1672struct `List` and the auto trait `Send`:
1673
1674```rust
1675struct List<T> {
1676 data: T,
1677 next: Option<Box<List<T>>>,
1678}
1679```
1680
1681Presuming that there is no explicit impl of `Send` for `List`, the
1682compiler will supply an automatic impl of the form:
1683
1684```rust
1685struct List<T> {
1686 data: T,
1687 next: Option<Box<List<T>>>,
1688}
1689
1690unsafe impl<T> Send for List<T>
1691where
1692 T: Send, // from the field `data`
1693 Option<Box<List<T>>>: Send, // from the field `next`
1694{ }
1695```
1696
1697Explicit impls may be either positive or negative. They take the form:
1698
1699```rust,ignore (partial-example)
1700impl<...> AutoTrait for StructName<..> { }
1701impl<...> !AutoTrait for StructName<..> { }
1702```
1703
1704## Coinduction: Auto traits permit cyclic matching
1705
1706Unlike ordinary trait matching, auto traits are **coinductive**. This
1707means, in short, that cycles which occur in trait matching are
1708considered ok. As an example, consider the recursive struct `List`
1709introduced in the previous section. In attempting to determine whether
1710`List: Send`, we would wind up in a cycle: to apply the impl, we must
1711show that `Option<Box<List>>: Send`, which will in turn require
1712`Box<List>: Send` and then finally `List: Send` again. Under ordinary
1713trait matching, this cycle would be an error, but for an auto trait it
1714is considered a successful match.
1715
1716## Items
1717
1718Auto traits cannot have any trait items, such as methods or associated types. This ensures that we can generate default implementations.
1719
1720## Supertraits
1721
1722Auto traits cannot have supertraits. This is for soundness reasons, as the interaction of coinduction with implied bounds is difficult to reconcile.
1723"##,
1724 },
1725 Lint {
1726 label: "box_patterns",
1727 description: r##"# `box_patterns`
1728
1729The tracking issue for this feature is: [#29641]
1730
1731[#29641]: https://github.com/rust-lang/rust/issues/29641
1732
1733See also [`box_syntax`](box-syntax.md)
1734
1735------------------------
1736
1737Box patterns let you match on `Box<T>`s:
1738
1739
1740```rust
1741#![feature(box_patterns)]
1742
1743fn main() {
1744 let b = Some(Box::new(5));
1745 match b {
1746 Some(box n) if n < 0 => {
1747 println!("Box contains negative number {}", n);
1748 },
1749 Some(box n) if n >= 0 => {
1750 println!("Box contains non-negative number {}", n);
1751 },
1752 None => {
1753 println!("No box");
1754 },
1755 _ => unreachable!()
1756 }
1757}
1758```
1759"##,
1760 },
1761 Lint {
1762 label: "box_syntax",
1763 description: r##"# `box_syntax`
1764
1765The tracking issue for this feature is: [#49733]
1766
1767[#49733]: https://github.com/rust-lang/rust/issues/49733
1768
1769See also [`box_patterns`](box-patterns.md)
1770
1771------------------------
1772
1773Currently the only stable way to create a `Box` is via the `Box::new` method.
1774Also it is not possible in stable Rust to destructure a `Box` in a match
1775pattern. The unstable `box` keyword can be used to create a `Box`. An example
1776usage would be:
1777
1778```rust
1779#![feature(box_syntax)]
1780
1781fn main() {
1782 let b = box 5;
1783}
1784```
1785"##,
1786 },
1787 Lint {
1788 label: "c_unwind",
1789 description: r##"# `c_unwind`
1790
1791The tracking issue for this feature is: [#74990]
1792
1793[#74990]: https://github.com/rust-lang/rust/issues/74990
1794
1795------------------------
1796
1797Introduces four new ABI strings: "C-unwind", "stdcall-unwind",
1798"thiscall-unwind", and "system-unwind". These enable unwinding from other
1799languages (such as C++) into Rust frames and from Rust into other languages.
1800
1801See [RFC 2945] for more information.
1802
1803[RFC 2945]: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md
1804"##,
1805 },
1806 Lint {
1807 label: "c_variadic",
1808 description: r##"# `c_variadic`
1809
1810The tracking issue for this feature is: [#44930]
1811
1812[#44930]: https://github.com/rust-lang/rust/issues/44930
1813
1814------------------------
1815
1816The `c_variadic` language feature enables C-variadic functions to be
1817defined in Rust. The may be called both from within Rust and via FFI.
1818
1819## Examples
1820
1821```rust
1822#![feature(c_variadic)]
1823
1824pub unsafe extern "C" fn add(n: usize, mut args: ...) -> usize {
1825 let mut sum = 0;
1826 for _ in 0..n {
1827 sum += args.arg::<usize>();
1828 }
1829 sum
1830}
1831```
1832"##,
1833 },
1834 Lint {
1835 label: "c_variadic",
1836 description: r##"# `c_variadic`
1837
1838The tracking issue for this feature is: [#44930]
1839
1840[#44930]: https://github.com/rust-lang/rust/issues/44930
1841
1842------------------------
1843
1844The `c_variadic` library feature exposes the `VaList` structure,
1845Rust's analogue of C's `va_list` type.
1846
1847## Examples
1848
1849```rust
1850#![feature(c_variadic)]
1851
1852use std::ffi::VaList;
1853
1854pub unsafe extern "C" fn vadd(n: usize, mut args: VaList) -> usize {
1855 let mut sum = 0;
1856 for _ in 0..n {
1857 sum += args.arg::<usize>();
1858 }
1859 sum
1860}
1861```
1862"##,
1863 },
1864 Lint {
1865 label: "c_void_variant",
1866 description: r##"# `c_void_variant`
1867
1868This feature is internal to the Rust compiler and is not intended for general use.
1869
1870------------------------
1871"##,
1872 },
1873 Lint {
1874 label: "cfg_panic",
1875 description: r##"# `cfg_panic`
1876
1877The tracking issue for this feature is: [#77443]
1878
1879[#77443]: https://github.com/rust-lang/rust/issues/77443
1880
1881------------------------
1882
1883The `cfg_panic` feature makes it possible to execute different code
1884depending on the panic strategy.
1885
1886Possible values at the moment are `"unwind"` or `"abort"`, although
1887it is possible that new panic strategies may be added to Rust in the
1888future.
1889
1890## Examples
1891
1892```rust
1893#![feature(cfg_panic)]
1894
1895#[cfg(panic = "unwind")]
1896fn a() {
1897 // ...
1898}
1899
1900#[cfg(not(panic = "unwind"))]
1901fn a() {
1902 // ...
1903}
1904
1905fn b() {
1906 if cfg!(panic = "abort") {
1907 // ...
1908 } else {
1909 // ...
1910 }
1911}
1912```
1913"##,
1914 },
1915 Lint {
1916 label: "cfg_sanitize",
1917 description: r##"# `cfg_sanitize`
1918
1919The tracking issue for this feature is: [#39699]
1920
1921[#39699]: https://github.com/rust-lang/rust/issues/39699
1922
1923------------------------
1924
1925The `cfg_sanitize` feature makes it possible to execute different code
1926depending on whether a particular sanitizer is enabled or not.
1927
1928## Examples
1929
1930```rust
1931#![feature(cfg_sanitize)]
1932
1933#[cfg(sanitize = "thread")]
1934fn a() {
1935 // ...
1936}
1937
1938#[cfg(not(sanitize = "thread"))]
1939fn a() {
1940 // ...
1941}
1942
1943fn b() {
1944 if cfg!(sanitize = "leak") {
1945 // ...
1946 } else {
1947 // ...
1948 }
1949}
1950```
1951"##,
1952 },
1953 Lint {
1954 label: "cfg_version",
1955 description: r##"# `cfg_version`
1956
1957The tracking issue for this feature is: [#64796]
1958
1959[#64796]: https://github.com/rust-lang/rust/issues/64796
1960
1961------------------------
1962
1963The `cfg_version` feature makes it possible to execute different code
1964depending on the compiler version. It will return true if the compiler
1965version is greater than or equal to the specified version.
1966
1967## Examples
1968
1969```rust
1970#![feature(cfg_version)]
1971
1972#[cfg(version("1.42"))] // 1.42 and above
1973fn a() {
1974 // ...
1975}
1976
1977#[cfg(not(version("1.42")))] // 1.41 and below
1978fn a() {
1979 // ...
1980}
1981
1982fn b() {
1983 if cfg!(version("1.42")) {
1984 // ...
1985 } else {
1986 // ...
1987 }
1988}
1989```
1990"##,
1991 },
1992 Lint {
1993 label: "char_error_internals",
1994 description: r##"# `char_error_internals`
1995
1996This feature is internal to the Rust compiler and is not intended for general use.
1997
1998------------------------
1999"##,
2000 },
2001 Lint {
2002 label: "cmse_nonsecure_entry",
2003 description: r##"# `cmse_nonsecure_entry`
2004
2005The tracking issue for this feature is: [#75835]
2006
2007[#75835]: https://github.com/rust-lang/rust/issues/75835
2008
2009------------------------
2010
2011The [TrustZone-M
2012feature](https://developer.arm.com/documentation/100690/latest/) is available
2013for targets with the Armv8-M architecture profile (`thumbv8m` in their target
2014name).
2015LLVM, the Rust compiler and the linker are providing
2016[support](https://developer.arm.com/documentation/ecm0359818/latest/) for the
2017TrustZone-M feature.
2018
2019One of the things provided, with this unstable feature, is the
2020`cmse_nonsecure_entry` attribute. This attribute marks a Secure function as an
2021entry function (see [section
20225.4](https://developer.arm.com/documentation/ecm0359818/latest/) for details).
2023With this attribute, the compiler will do the following:
2024* add a special symbol on the function which is the `__acle_se_` prefix and the
2025 standard function name
2026* constrain the number of parameters to avoid using the Non-Secure stack
2027* before returning from the function, clear registers that might contain Secure
2028 information
2029* use the `BXNS` instruction to return
2030
2031Because the stack can not be used to pass parameters, there will be compilation
2032errors if:
2033* the total size of all parameters is too big (for example more than four 32
2034 bits integers)
2035* the entry function is not using a C ABI
2036
2037The special symbol `__acle_se_` will be used by the linker to generate a secure
2038gateway veneer.
2039
2040<!-- NOTE(ignore) this example is specific to thumbv8m targets -->
2041
2042``` rust,ignore
2043#![feature(cmse_nonsecure_entry)]
2044
2045#[no_mangle]
2046#[cmse_nonsecure_entry]
2047pub extern "C" fn entry_function(input: u32) -> u32 {
2048 input + 6
2049}
2050```
2051
2052``` text
2053$ rustc --emit obj --crate-type lib --target thumbv8m.main-none-eabi function.rs
2054$ arm-none-eabi-objdump -D function.o
2055
205600000000 <entry_function>:
2057 0: b580 push {r7, lr}
2058 2: 466f mov r7, sp
2059 4: b082 sub sp, #8
2060 6: 9001 str r0, [sp, #4]
2061 8: 1d81 adds r1, r0, #6
2062 a: 460a mov r2, r1
2063 c: 4281 cmp r1, r0
2064 e: 9200 str r2, [sp, #0]
2065 10: d30b bcc.n 2a <entry_function+0x2a>
2066 12: e7ff b.n 14 <entry_function+0x14>
2067 14: 9800 ldr r0, [sp, #0]
2068 16: b002 add sp, #8
2069 18: e8bd 4080 ldmia.w sp!, {r7, lr}
2070 1c: 4671 mov r1, lr
2071 1e: 4672 mov r2, lr
2072 20: 4673 mov r3, lr
2073 22: 46f4 mov ip, lr
2074 24: f38e 8800 msr CPSR_f, lr
2075 28: 4774 bxns lr
2076 2a: f240 0000 movw r0, #0
2077 2e: f2c0 0000 movt r0, #0
2078 32: f240 0200 movw r2, #0
2079 36: f2c0 0200 movt r2, #0
2080 3a: 211c movs r1, #28
2081 3c: f7ff fffe bl 0 <_ZN4core9panicking5panic17h5c028258ca2fb3f5E>
2082 40: defe udf #254 ; 0xfe
2083```
2084"##,
2085 },
2086 Lint {
2087 label: "compiler_builtins",
2088 description: r##"# `compiler_builtins`
2089
2090This feature is internal to the Rust compiler and is not intended for general use.
2091
2092------------------------
2093"##,
2094 },
2095 Lint {
2096 label: "concat_idents",
2097 description: r##"# `concat_idents`
2098
2099The tracking issue for this feature is: [#29599]
2100
2101[#29599]: https://github.com/rust-lang/rust/issues/29599
2102
2103------------------------
2104
2105The `concat_idents` feature adds a macro for concatenating multiple identifiers
2106into one identifier.
2107
2108## Examples
2109
2110```rust
2111#![feature(concat_idents)]
2112
2113fn main() {
2114 fn foobar() -> u32 { 23 }
2115 let f = concat_idents!(foo, bar);
2116 assert_eq!(f(), 23);
2117}
2118```
2119"##,
2120 },
2121 Lint {
2122 label: "const_eval_limit",
2123 description: r##"# `const_eval_limit`
2124
2125The tracking issue for this feature is: [#67217]
2126
2127[#67217]: https://github.com/rust-lang/rust/issues/67217
2128
2129The `const_eval_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`.
2130"##,
2131 },
2132 Lint {
2133 label: "core_intrinsics",
2134 description: r##"# `core_intrinsics`
2135
2136This feature is internal to the Rust compiler and is not intended for general use.
2137
2138------------------------
2139"##,
2140 },
2141 Lint {
2142 label: "core_panic",
2143 description: r##"# `core_panic`
2144
2145This feature is internal to the Rust compiler and is not intended for general use.
2146
2147------------------------
2148"##,
2149 },
2150 Lint {
2151 label: "core_private_bignum",
2152 description: r##"# `core_private_bignum`
2153
2154This feature is internal to the Rust compiler and is not intended for general use.
2155
2156------------------------
2157"##,
2158 },
2159 Lint {
2160 label: "core_private_diy_float",
2161 description: r##"# `core_private_diy_float`
2162
2163This feature is internal to the Rust compiler and is not intended for general use.
2164
2165------------------------
2166"##,
2167 },
2168 Lint {
2169 label: "crate_visibility_modifier",
2170 description: r##"# `crate_visibility_modifier`
2171
2172The tracking issue for this feature is: [#53120]
2173
2174[#53120]: https://github.com/rust-lang/rust/issues/53120
2175
2176-----
2177
2178The `crate_visibility_modifier` feature allows the `crate` keyword to be used
2179as a visibility modifier synonymous to `pub(crate)`, indicating that a type
2180(function, _&c._) is to be visible to the entire enclosing crate, but not to
2181other crates.
2182
2183```rust
2184#![feature(crate_visibility_modifier)]
2185
2186crate struct Foo {
2187 bar: usize,
2188}
2189```
2190"##,
2191 },
2192 Lint {
2193 label: "custom_test_frameworks",
2194 description: r##"# `custom_test_frameworks`
2195
2196The tracking issue for this feature is: [#50297]
2197
2198[#50297]: https://github.com/rust-lang/rust/issues/50297
2199
2200------------------------
2201
2202The `custom_test_frameworks` feature allows the use of `#[test_case]` and `#![test_runner]`.
2203Any function, const, or static can be annotated with `#[test_case]` causing it to be aggregated (like `#[test]`)
2204and be passed to the test runner determined by the `#![test_runner]` crate attribute.
2205
2206```rust
2207#![feature(custom_test_frameworks)]
2208#![test_runner(my_runner)]
2209
2210fn my_runner(tests: &[&i32]) {
2211 for t in tests {
2212 if **t == 0 {
2213 println!("PASSED");
2214 } else {
2215 println!("FAILED");
2216 }
2217 }
2218}
2219
2220#[test_case]
2221const WILL_PASS: i32 = 0;
2222
2223#[test_case]
2224const WILL_FAIL: i32 = 4;
2225```
2226"##,
2227 },
2228 Lint {
2229 label: "dec2flt",
2230 description: r##"# `dec2flt`
2231
2232This feature is internal to the Rust compiler and is not intended for general use.
2233
2234------------------------
2235"##,
2236 },
2237 Lint {
2238 label: "default_free_fn",
2239 description: r##"# `default_free_fn`
2240
2241The tracking issue for this feature is: [#73014]
2242
2243[#73014]: https://github.com/rust-lang/rust/issues/73014
2244
2245------------------------
2246
2247Adds a free `default()` function to the `std::default` module. This function
2248just forwards to [`Default::default()`], but may remove repetition of the word
2249"default" from the call site.
2250
2251[`Default::default()`]: https://doc.rust-lang.org/nightly/std/default/trait.Default.html#tymethod.default
2252
2253Here is an example:
2254
2255```rust
2256#![feature(default_free_fn)]
2257use std::default::default;
2258
2259#[derive(Default)]
2260struct AppConfig {
2261 foo: FooConfig,
2262 bar: BarConfig,
2263}
2264
2265#[derive(Default)]
2266struct FooConfig {
2267 foo: i32,
2268}
2269
2270#[derive(Default)]
2271struct BarConfig {
2272 bar: f32,
2273 baz: u8,
2274}
2275
2276fn main() {
2277 let options = AppConfig {
2278 foo: default(),
2279 bar: BarConfig {
2280 bar: 10.1,
2281 ..default()
2282 },
2283 };
2284}
2285```
2286"##,
2287 },
2288 Lint {
2289 label: "derive_clone_copy",
2290 description: r##"# `derive_clone_copy`
2291
2292This feature is internal to the Rust compiler and is not intended for general use.
2293
2294------------------------
2295"##,
2296 },
2297 Lint {
2298 label: "derive_eq",
2299 description: r##"# `derive_eq`
2300
2301This feature is internal to the Rust compiler and is not intended for general use.
2302
2303------------------------
2304"##,
2305 },
2306 Lint {
2307 label: "doc_cfg",
2308 description: r##"# `doc_cfg`
2309
2310The tracking issue for this feature is: [#43781]
2311
2312------
2313
2314The `doc_cfg` feature allows an API be documented as only available in some specific platforms.
2315This attribute has two effects:
2316
23171. In the annotated item's documentation, there will be a message saying "This is supported on
2318 (platform) only".
2319
23202. The item's doc-tests will only run on the specific platform.
2321
2322In addition to allowing the use of the `#[doc(cfg)]` attribute, this feature enables the use of a
2323special conditional compilation flag, `#[cfg(doc)]`, set whenever building documentation on your
2324crate.
2325
2326This feature was introduced as part of PR [#43348] to allow the platform-specific parts of the
2327standard library be documented.
2328
2329```rust
2330#![feature(doc_cfg)]
2331
2332#[cfg(any(windows, doc))]
2333#[doc(cfg(windows))]
2334/// The application's icon in the notification area (a.k.a. system tray).
2335///
2336/// # Examples
2337///
2338/// ```no_run
2339/// extern crate my_awesome_ui_library;
2340/// use my_awesome_ui_library::current_app;
2341/// use my_awesome_ui_library::windows::notification;
2342///
2343/// let icon = current_app().get::<notification::Icon>();
2344/// icon.show();
2345/// icon.show_message("Hello");
2346/// ```
2347pub struct Icon {
2348 // ...
2349}
2350```
2351
2352[#43781]: https://github.com/rust-lang/rust/issues/43781
2353[#43348]: https://github.com/rust-lang/rust/issues/43348
2354"##,
2355 },
2356 Lint {
2357 label: "doc_masked",
2358 description: r##"# `doc_masked`
2359
2360The tracking issue for this feature is: [#44027]
2361
2362-----
2363
2364The `doc_masked` feature allows a crate to exclude types from a given crate from appearing in lists
2365of trait implementations. The specifics of the feature are as follows:
2366
23671. When rustdoc encounters an `extern crate` statement annotated with a `#[doc(masked)]` attribute,
2368 it marks the crate as being masked.
2369
23702. When listing traits a given type implements, rustdoc ensures that traits from masked crates are
2371 not emitted into the documentation.
2372
23733. When listing types that implement a given trait, rustdoc ensures that types from masked crates
2374 are not emitted into the documentation.
2375
2376This feature was introduced in PR [#44026] to ensure that compiler-internal and
2377implementation-specific types and traits were not included in the standard library's documentation.
2378Such types would introduce broken links into the documentation.
2379
2380[#44026]: https://github.com/rust-lang/rust/pull/44026
2381[#44027]: https://github.com/rust-lang/rust/pull/44027
2382"##,
2383 },
2384 Lint {
2385 label: "doc_notable_trait",
2386 description: r##"# `doc_notable_trait`
2387
2388The tracking issue for this feature is: [#45040]
2389
2390The `doc_notable_trait` feature allows the use of the `#[doc(notable_trait)]`
2391attribute, which will display the trait in a "Notable traits" dialog for
2392functions returning types that implement the trait. For example, this attribute
2393is applied to the `Iterator`, `Future`, `io::Read`, and `io::Write` traits in
2394the standard library.
2395
2396You can do this on your own traits like so:
2397
2398```
2399#![feature(doc_notable_trait)]
2400
2401#[doc(notable_trait)]
2402pub trait MyTrait {}
2403
2404pub struct MyStruct;
2405impl MyTrait for MyStruct {}
2406
2407/// The docs for this function will have a button that displays a dialog about
2408/// `MyStruct` implementing `MyTrait`.
2409pub fn my_fn() -> MyStruct { MyStruct }
2410```
2411
2412This feature was originally implemented in PR [#45039].
2413
2414See also its documentation in [the rustdoc book][rustdoc-book-notable_trait].
2415
2416[#45040]: https://github.com/rust-lang/rust/issues/45040
2417[#45039]: https://github.com/rust-lang/rust/pull/45039
2418[rustdoc-book-notable_trait]: ../../rustdoc/unstable-features.html#adding-your-trait-to-the-notable-traits-dialog
2419"##,
2420 },
2421 Lint {
2422 label: "external_doc",
2423 description: r##"# `external_doc`
2424
2425The tracking issue for this feature is: [#44732]
2426
2427The `external_doc` feature allows the use of the `include` parameter to the `#[doc]` attribute, to
2428include external files in documentation. Use the attribute in place of, or in addition to, regular
2429doc comments and `#[doc]` attributes, and `rustdoc` will load the given file when it renders
2430documentation for your crate.
2431
2432With the following files in the same directory:
2433
2434`external-doc.md`:
2435
2436```markdown
2437# My Awesome Type
2438
2439This is the documentation for this spectacular type.
2440```
2441
2442`lib.rs`:
2443
2444```no_run (needs-external-files)
2445#![feature(external_doc)]
2446
2447#[doc(include = "external-doc.md")]
2448pub struct MyAwesomeType;
2449```
2450
2451`rustdoc` will load the file `external-doc.md` and use it as the documentation for the `MyAwesomeType`
2452struct.
2453
2454When locating files, `rustdoc` will base paths in the `src/` directory, as if they were alongside the
2455`lib.rs` for your crate. So if you want a `docs/` folder to live alongside the `src/` directory,
2456start your paths with `../docs/` for `rustdoc` to properly find the file.
2457
2458This feature was proposed in [RFC #1990] and initially implemented in PR [#44781].
2459
2460[#44732]: https://github.com/rust-lang/rust/issues/44732
2461[RFC #1990]: https://github.com/rust-lang/rfcs/pull/1990
2462[#44781]: https://github.com/rust-lang/rust/pull/44781
2463"##,
2464 },
2465 Lint {
2466 label: "fd",
2467 description: r##"# `fd`
2468
2469This feature is internal to the Rust compiler and is not intended for general use.
2470
2471------------------------
2472"##,
2473 },
2474 Lint {
2475 label: "fd_read",
2476 description: r##"# `fd_read`
2477
2478This feature is internal to the Rust compiler and is not intended for general use.
2479
2480------------------------
2481"##,
2482 },
2483 Lint {
2484 label: "ffi_const",
2485 description: r##"# `ffi_const`
2486
2487The tracking issue for this feature is: [#58328]
2488
2489------
2490
2491The `#[ffi_const]` attribute applies clang's `const` attribute to foreign
2492functions declarations.
2493
2494That is, `#[ffi_const]` functions shall have no effects except for its return
2495value, which can only depend on the values of the function parameters, and is
2496not affected by changes to the observable state of the program.
2497
2498Applying the `#[ffi_const]` attribute to a function that violates these
2499requirements is undefined behaviour.
2500
2501This attribute enables Rust to perform common optimizations, like sub-expression
2502elimination, and it can avoid emitting some calls in repeated invocations of the
2503function with the same argument values regardless of other operations being
2504performed in between these functions calls (as opposed to `#[ffi_pure]`
2505functions).
2506
2507## Pitfalls
2508
2509A `#[ffi_const]` function can only read global memory that would not affect
2510its return value for the whole execution of the program (e.g. immutable global
2511memory). `#[ffi_const]` functions are referentially-transparent and therefore
2512more strict than `#[ffi_pure]` functions.
2513
2514A common pitfall involves applying the `#[ffi_const]` attribute to a
2515function that reads memory through pointer arguments which do not necessarily
2516point to immutable global memory.
2517
2518A `#[ffi_const]` function that returns unit has no effect on the abstract
2519machine's state, and a `#[ffi_const]` function cannot be `#[ffi_pure]`.
2520
2521A `#[ffi_const]` function must not diverge, neither via a side effect (e.g. a
2522call to `abort`) nor by infinite loops.
2523
2524When translating C headers to Rust FFI, it is worth verifying for which targets
2525the `const` attribute is enabled in those headers, and using the appropriate
2526`cfg` macros in the Rust side to match those definitions. While the semantics of
2527`const` are implemented identically by many C and C++ compilers, e.g., clang,
2528[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily
2529implemented in this way on all of them. It is therefore also worth verifying
2530that the semantics of the C toolchain used to compile the binary being linked
2531against are compatible with those of the `#[ffi_const]`.
2532
2533[#58328]: https://github.com/rust-lang/rust/issues/58328
2534[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacgigch.html
2535[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute
2536[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_const.htm
2537"##,
2538 },
2539 Lint {
2540 label: "ffi_pure",
2541 description: r##"# `ffi_pure`
2542
2543The tracking issue for this feature is: [#58329]
2544
2545------
2546
2547The `#[ffi_pure]` attribute applies clang's `pure` attribute to foreign
2548functions declarations.
2549
2550That is, `#[ffi_pure]` functions shall have no effects except for its return
2551value, which shall not change across two consecutive function calls with
2552the same parameters.
2553
2554Applying the `#[ffi_pure]` attribute to a function that violates these
2555requirements is undefined behavior.
2556
2557This attribute enables Rust to perform common optimizations, like sub-expression
2558elimination and loop optimizations. Some common examples of pure functions are
2559`strlen` or `memcmp`.
2560
2561These optimizations are only applicable when the compiler can prove that no
2562program state observable by the `#[ffi_pure]` function has changed between calls
2563of the function, which could alter the result. See also the `#[ffi_const]`
2564attribute, which provides stronger guarantees regarding the allowable behavior
2565of a function, enabling further optimization.
2566
2567## Pitfalls
2568
2569A `#[ffi_pure]` function can read global memory through the function
2570parameters (e.g. pointers), globals, etc. `#[ffi_pure]` functions are not
2571referentially-transparent, and are therefore more relaxed than `#[ffi_const]`
2572functions.
2573
2574However, accessing global memory through volatile or atomic reads can violate the
2575requirement that two consecutive function calls shall return the same value.
2576
2577A `pure` function that returns unit has no effect on the abstract machine's
2578state.
2579
2580A `#[ffi_pure]` function must not diverge, neither via a side effect (e.g. a
2581call to `abort`) nor by infinite loops.
2582
2583When translating C headers to Rust FFI, it is worth verifying for which targets
2584the `pure` attribute is enabled in those headers, and using the appropriate
2585`cfg` macros in the Rust side to match those definitions. While the semantics of
2586`pure` are implemented identically by many C and C++ compilers, e.g., clang,
2587[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily
2588implemented in this way on all of them. It is therefore also worth verifying
2589that the semantics of the C toolchain used to compile the binary being linked
2590against are compatible with those of the `#[ffi_pure]`.
2591
2592
2593[#58329]: https://github.com/rust-lang/rust/issues/58329
2594[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacigdac.html
2595[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute
2596[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_pure.htm
2597"##,
2598 },
2599 Lint {
2600 label: "flt2dec",
2601 description: r##"# `flt2dec`
2602
2603This feature is internal to the Rust compiler and is not intended for general use.
2604
2605------------------------
2606"##,
2607 },
2608 Lint {
2609 label: "fmt_internals",
2610 description: r##"# `fmt_internals`
2611
2612This feature is internal to the Rust compiler and is not intended for general use.
2613
2614------------------------
2615"##,
2616 },
2617 Lint {
2618 label: "fn_traits",
2619 description: r##"# `fn_traits`
2620
2621The tracking issue for this feature is [#29625]
2622
2623See Also: [`unboxed_closures`](../language-features/unboxed-closures.md)
2624
2625[#29625]: https://github.com/rust-lang/rust/issues/29625
2626
2627----
2628
2629The `fn_traits` feature allows for implementation of the [`Fn*`] traits
2630for creating custom closure-like types.
2631
2632[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
2633
2634```rust
2635#![feature(unboxed_closures)]
2636#![feature(fn_traits)]
2637
2638struct Adder {
2639 a: u32
2640}
2641
2642impl FnOnce<(u32, )> for Adder {
2643 type Output = u32;
2644 extern "rust-call" fn call_once(self, b: (u32, )) -> Self::Output {
2645 self.a + b.0
2646 }
2647}
2648
2649fn main() {
2650 let adder = Adder { a: 3 };
2651 assert_eq!(adder(2), 5);
2652}
2653```
2654"##,
2655 },
2656 Lint {
2657 label: "format_args_capture",
2658 description: r##"# `format_args_capture`
2659
2660The tracking issue for this feature is: [#67984]
2661
2662[#67984]: https://github.com/rust-lang/rust/issues/67984
2663
2664------------------------
2665
2666Enables `format_args!` (and macros which use `format_args!` in their implementation, such
2667as `format!`, `print!` and `panic!`) to capture variables from the surrounding scope.
2668This avoids the need to pass named parameters when the binding in question
2669already exists in scope.
2670
2671```rust
2672#![feature(format_args_capture)]
2673
2674let (person, species, name) = ("Charlie Brown", "dog", "Snoopy");
2675
2676// captures named argument `person`
2677print!("Hello {person}");
2678
2679// captures named arguments `species` and `name`
2680format!("The {species}'s name is {name}.");
2681```
2682
2683This also works for formatting parameters such as width and precision:
2684
2685```rust
2686#![feature(format_args_capture)]
2687
2688let precision = 2;
2689let s = format!("{:.precision$}", 1.324223);
2690
2691assert_eq!(&s, "1.32");
2692```
2693
2694A non-exhaustive list of macros which benefit from this functionality include:
2695- `format!`
2696- `print!` and `println!`
2697- `eprint!` and `eprintln!`
2698- `write!` and `writeln!`
2699- `panic!`
2700- `unreachable!`
2701- `unimplemented!`
2702- `todo!`
2703- `assert!` and similar
2704- macros in many thirdparty crates, such as `log`
2705"##,
2706 },
2707 Lint {
2708 label: "generators",
2709 description: r##"# `generators`
2710
2711The tracking issue for this feature is: [#43122]
2712
2713[#43122]: https://github.com/rust-lang/rust/issues/43122
2714
2715------------------------
2716
2717The `generators` feature gate in Rust allows you to define generator or
2718coroutine literals. A generator is a "resumable function" that syntactically
2719resembles a closure but compiles to much different semantics in the compiler
2720itself. The primary feature of a generator is that it can be suspended during
2721execution to be resumed at a later date. Generators use the `yield` keyword to
2722"return", and then the caller can `resume` a generator to resume execution just
2723after the `yield` keyword.
2724
2725Generators are an extra-unstable feature in the compiler right now. Added in
2726[RFC 2033] they're mostly intended right now as a information/constraint
2727gathering phase. The intent is that experimentation can happen on the nightly
2728compiler before actual stabilization. A further RFC will be required to
2729stabilize generators/coroutines and will likely contain at least a few small
2730tweaks to the overall design.
2731
2732[RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033
2733
2734A syntactical example of a generator is:
2735
2736```rust
2737#![feature(generators, generator_trait)]
2738
2739use std::ops::{Generator, GeneratorState};
2740use std::pin::Pin;
2741
2742fn main() {
2743 let mut generator = || {
2744 yield 1;
2745 return "foo"
2746 };
2747
2748 match Pin::new(&mut generator).resume(()) {
2749 GeneratorState::Yielded(1) => {}
2750 _ => panic!("unexpected value from resume"),
2751 }
2752 match Pin::new(&mut generator).resume(()) {
2753 GeneratorState::Complete("foo") => {}
2754 _ => panic!("unexpected value from resume"),
2755 }
2756}
2757```
2758
2759Generators are closure-like literals which can contain a `yield` statement. The
2760`yield` statement takes an optional expression of a value to yield out of the
2761generator. All generator literals implement the `Generator` trait in the
2762`std::ops` module. The `Generator` trait has one main method, `resume`, which
2763resumes execution of the generator at the previous suspension point.
2764
2765An example of the control flow of generators is that the following example
2766prints all numbers in order:
2767
2768```rust
2769#![feature(generators, generator_trait)]
2770
2771use std::ops::Generator;
2772use std::pin::Pin;
2773
2774fn main() {
2775 let mut generator = || {
2776 println!("2");
2777 yield;
2778 println!("4");
2779 };
2780
2781 println!("1");
2782 Pin::new(&mut generator).resume(());
2783 println!("3");
2784 Pin::new(&mut generator).resume(());
2785 println!("5");
2786}
2787```
2788
2789At this time the main intended use case of generators is an implementation
2790primitive for async/await syntax, but generators will likely be extended to
2791ergonomic implementations of iterators and other primitives in the future.
2792Feedback on the design and usage is always appreciated!
2793
2794### The `Generator` trait
2795
2796The `Generator` trait in `std::ops` currently looks like:
2797
2798```rust
2799# #![feature(arbitrary_self_types, generator_trait)]
2800# use std::ops::GeneratorState;
2801# use std::pin::Pin;
2802
2803pub trait Generator<R = ()> {
2804 type Yield;
2805 type Return;
2806 fn resume(self: Pin<&mut Self>, resume: R) -> GeneratorState<Self::Yield, Self::Return>;
2807}
2808```
2809
2810The `Generator::Yield` type is the type of values that can be yielded with the
2811`yield` statement. The `Generator::Return` type is the returned type of the
2812generator. This is typically the last expression in a generator's definition or
2813any value passed to `return` in a generator. The `resume` function is the entry
2814point for executing the `Generator` itself.
2815
2816The return value of `resume`, `GeneratorState`, looks like:
2817
2818```rust
2819pub enum GeneratorState<Y, R> {
2820 Yielded(Y),
2821 Complete(R),
2822}
2823```
2824
2825The `Yielded` variant indicates that the generator can later be resumed. This
2826corresponds to a `yield` point in a generator. The `Complete` variant indicates
2827that the generator is complete and cannot be resumed again. Calling `resume`
2828after a generator has returned `Complete` will likely result in a panic of the
2829program.
2830
2831### Closure-like semantics
2832
2833The closure-like syntax for generators alludes to the fact that they also have
2834closure-like semantics. Namely:
2835
2836* When created, a generator executes no code. A closure literal does not
2837 actually execute any of the closure's code on construction, and similarly a
2838 generator literal does not execute any code inside the generator when
2839 constructed.
2840
2841* Generators can capture outer variables by reference or by move, and this can
2842 be tweaked with the `move` keyword at the beginning of the closure. Like
2843 closures all generators will have an implicit environment which is inferred by
2844 the compiler. Outer variables can be moved into a generator for use as the
2845 generator progresses.
2846
2847* Generator literals produce a value with a unique type which implements the
2848 `std::ops::Generator` trait. This allows actual execution of the generator
2849 through the `Generator::resume` method as well as also naming it in return
2850 types and such.
2851
2852* Traits like `Send` and `Sync` are automatically implemented for a `Generator`
2853 depending on the captured variables of the environment. Unlike closures,
2854 generators also depend on variables live across suspension points. This means
2855 that although the ambient environment may be `Send` or `Sync`, the generator
2856 itself may not be due to internal variables live across `yield` points being
2857 not-`Send` or not-`Sync`. Note that generators do
2858 not implement traits like `Copy` or `Clone` automatically.
2859
2860* Whenever a generator is dropped it will drop all captured environment
2861 variables.
2862
2863### Generators as state machines
2864
2865In the compiler, generators are currently compiled as state machines. Each
2866`yield` expression will correspond to a different state that stores all live
2867variables over that suspension point. Resumption of a generator will dispatch on
2868the current state and then execute internally until a `yield` is reached, at
2869which point all state is saved off in the generator and a value is returned.
2870
2871Let's take a look at an example to see what's going on here:
2872
2873```rust
2874#![feature(generators, generator_trait)]
2875
2876use std::ops::Generator;
2877use std::pin::Pin;
2878
2879fn main() {
2880 let ret = "foo";
2881 let mut generator = move || {
2882 yield 1;
2883 return ret
2884 };
2885
2886 Pin::new(&mut generator).resume(());
2887 Pin::new(&mut generator).resume(());
2888}
2889```
2890
2891This generator literal will compile down to something similar to:
2892
2893```rust
2894#![feature(arbitrary_self_types, generators, generator_trait)]
2895
2896use std::ops::{Generator, GeneratorState};
2897use std::pin::Pin;
2898
2899fn main() {
2900 let ret = "foo";
2901 let mut generator = {
2902 enum __Generator {
2903 Start(&'static str),
2904 Yield1(&'static str),
2905 Done,
2906 }
2907
2908 impl Generator for __Generator {
2909 type Yield = i32;
2910 type Return = &'static str;
2911
2912 fn resume(mut self: Pin<&mut Self>, resume: ()) -> GeneratorState<i32, &'static str> {
2913 use std::mem;
2914 match mem::replace(&mut *self, __Generator::Done) {
2915 __Generator::Start(s) => {
2916 *self = __Generator::Yield1(s);
2917 GeneratorState::Yielded(1)
2918 }
2919
2920 __Generator::Yield1(s) => {
2921 *self = __Generator::Done;
2922 GeneratorState::Complete(s)
2923 }
2924
2925 __Generator::Done => {
2926 panic!("generator resumed after completion")
2927 }
2928 }
2929 }
2930 }
2931
2932 __Generator::Start(ret)
2933 };
2934
2935 Pin::new(&mut generator).resume(());
2936 Pin::new(&mut generator).resume(());
2937}
2938```
2939
2940Notably here we can see that the compiler is generating a fresh type,
2941`__Generator` in this case. This type has a number of states (represented here
2942as an `enum`) corresponding to each of the conceptual states of the generator.
2943At the beginning we're closing over our outer variable `foo` and then that
2944variable is also live over the `yield` point, so it's stored in both states.
2945
2946When the generator starts it'll immediately yield 1, but it saves off its state
2947just before it does so indicating that it has reached the yield point. Upon
2948resuming again we'll execute the `return ret` which returns the `Complete`
2949state.
2950
2951Here we can also note that the `Done` state, if resumed, panics immediately as
2952it's invalid to resume a completed generator. It's also worth noting that this
2953is just a rough desugaring, not a normative specification for what the compiler
2954does.
2955"##,
2956 },
2957 Lint {
2958 label: "global_asm",
2959 description: r##"# `global_asm`
2960
2961The tracking issue for this feature is: [#35119]
2962
2963[#35119]: https://github.com/rust-lang/rust/issues/35119
2964
2965------------------------
2966
2967The `global_asm!` macro allows the programmer to write arbitrary
2968assembly outside the scope of a function body, passing it through
2969`rustc` and `llvm` to the assembler. That is to say, `global_asm!` is
2970equivalent to assembling the asm with an external assembler and then
2971linking the resulting object file with the current crate.
2972
2973`global_asm!` fills a role not currently satisfied by either `asm!`
2974or `#[naked]` functions. The programmer has _all_ features of the
2975assembler at their disposal. The linker will expect to resolve any
2976symbols defined in the inline assembly, modulo any symbols marked as
2977external. It also means syntax for directives and assembly follow the
2978conventions of the assembler in your toolchain.
2979
2980A simple usage looks like this:
2981
2982```rust,ignore (requires-external-file)
2983#![feature(global_asm)]
2984# // you also need relevant target_arch cfgs
2985global_asm!(include_str!("something_neato.s"));
2986```
2987
2988And a more complicated usage looks like this:
2989
2990```rust,no_run
2991#![feature(global_asm)]
2992# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
2993# mod x86 {
2994
2995pub mod sally {
2996 global_asm!(
2997 ".global foo",
2998 "foo:",
2999 "jmp baz",
3000 );
3001
3002 #[no_mangle]
3003 pub unsafe extern "C" fn baz() {}
3004}
3005
3006// the symbols `foo` and `bar` are global, no matter where
3007// `global_asm!` was used.
3008extern "C" {
3009 fn foo();
3010 fn bar();
3011}
3012
3013pub mod harry {
3014 global_asm!(
3015 ".global bar",
3016 "bar:",
3017 "jmp quux",
3018 );
3019
3020 #[no_mangle]
3021 pub unsafe extern "C" fn quux() {}
3022}
3023# }
3024```
3025
3026You may use `global_asm!` multiple times, anywhere in your crate, in
3027whatever way suits you. However, you should not rely on assembler state
3028(e.g. assembler macros) defined in one `global_asm!` to be available in
3029another one. It is implementation-defined whether the multiple usages
3030are concatenated into one or assembled separately.
3031
3032`global_asm!` also supports `const` operands like `asm!`, which allows
3033constants defined in Rust to be used in assembly code:
3034
3035```rust,no_run
3036#![feature(global_asm)]
3037# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
3038# mod x86 {
3039const C: i32 = 1234;
3040global_asm!(
3041 ".global bar",
3042 "bar: .word {c}",
3043 c = const C,
3044);
3045# }
3046```
3047
3048The syntax for passing operands is the same as `asm!` except that only
3049`const` operands are allowed. Refer to the [asm](asm.md) documentation
3050for more details.
3051
3052On x86, the assembly code will use intel syntax by default. You can
3053override this by adding `options(att_syntax)` at the end of the macro
3054arguments list:
3055
3056```rust,no_run
3057#![feature(global_asm)]
3058# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
3059# mod x86 {
3060global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
3061// is equivalent to
3062global_asm!("mov ecx, {}", const 5);
3063# }
3064```
3065
3066------------------------
3067
3068If you don't need quite as much power and flexibility as
3069`global_asm!` provides, and you don't mind restricting your inline
3070assembly to `fn` bodies only, you might try the
3071[asm](asm.md) feature instead.
3072"##,
3073 },
3074 Lint {
3075 label: "impl_trait_in_bindings",
3076 description: r##"# `impl_trait_in_bindings`
3077
3078The tracking issue for this feature is: [#63065]
3079
3080[#63065]: https://github.com/rust-lang/rust/issues/63065
3081
3082------------------------
3083
3084The `impl_trait_in_bindings` feature gate lets you use `impl Trait` syntax in
3085`let`, `static`, and `const` bindings.
3086
3087A simple example is:
3088
3089```rust
3090#![feature(impl_trait_in_bindings)]
3091
3092use std::fmt::Debug;
3093
3094fn main() {
3095 let a: impl Debug + Clone = 42;
3096 let b = a.clone();
3097 println!("{:?}", b); // prints `42`
3098}
3099```
3100
3101Note however that because the types of `a` and `b` are opaque in the above
3102example, calling inherent methods or methods outside of the specified traits
3103(e.g., `a.abs()` or `b.abs()`) is not allowed, and yields an error.
3104"##,
3105 },
3106 Lint {
3107 label: "infer_static_outlives_requirements",
3108 description: r##"# `infer_static_outlives_requirements`
3109
3110The tracking issue for this feature is: [#54185]
3111
3112[#54185]: https://github.com/rust-lang/rust/issues/54185
3113
3114------------------------
3115The `infer_static_outlives_requirements` feature indicates that certain
3116`'static` outlives requirements can be inferred by the compiler rather than
3117stating them explicitly.
3118
3119Note: It is an accompanying feature to `infer_outlives_requirements`,
3120which must be enabled to infer outlives requirements.
3121
3122For example, currently generic struct definitions that contain
3123references, require where-clauses of the form T: 'static. By using
3124this feature the outlives predicates will be inferred, although
3125they may still be written explicitly.
3126
3127```rust,ignore (pseudo-Rust)
3128struct Foo<U> where U: 'static { // <-- currently required
3129 bar: Bar<U>
3130}
3131struct Bar<T: 'static> {
3132 x: T,
3133}
3134```
3135
3136
3137## Examples:
3138
3139```rust,ignore (pseudo-Rust)
3140#![feature(infer_outlives_requirements)]
3141#![feature(infer_static_outlives_requirements)]
3142
3143#[rustc_outlives]
3144// Implicitly infer U: 'static
3145struct Foo<U> {
3146 bar: Bar<U>
3147}
3148struct Bar<T: 'static> {
3149 x: T,
3150}
3151```
3152"##,
3153 },
3154 Lint {
3155 label: "inline_const",
3156 description: r##"# `inline_const`
3157
3158The tracking issue for this feature is: [#76001]
3159
3160------
3161
3162This feature allows you to use inline constant expressions. For example, you can
3163turn this code:
3164
3165```rust
3166# fn add_one(x: i32) -> i32 { x + 1 }
3167const MY_COMPUTATION: i32 = 1 + 2 * 3 / 4;
3168
3169fn main() {
3170 let x = add_one(MY_COMPUTATION);
3171}
3172```
3173
3174into this code:
3175
3176```rust
3177#![feature(inline_const)]
3178
3179# fn add_one(x: i32) -> i32 { x + 1 }
3180fn main() {
3181 let x = add_one(const { 1 + 2 * 3 / 4 });
3182}
3183```
3184
3185You can also use inline constant expressions in patterns:
3186
3187```rust
3188#![feature(inline_const)]
3189
3190const fn one() -> i32 { 1 }
3191
3192let some_int = 3;
3193match some_int {
3194 const { 1 + 2 } => println!("Matched 1 + 2"),
3195 const { one() } => println!("Matched const fn returning 1"),
3196 _ => println!("Didn't match anything :("),
3197}
3198```
3199
3200[#76001]: https://github.com/rust-lang/rust/issues/76001
3201"##,
3202 },
3203 Lint {
3204 label: "int_error_internals",
3205 description: r##"# `int_error_internals`
3206
3207This feature is internal to the Rust compiler and is not intended for general use.
3208
3209------------------------
3210"##,
3211 },
3212 Lint {
3213 label: "internal_output_capture",
3214 description: r##"# `internal_output_capture`
3215
3216This feature is internal to the Rust compiler and is not intended for general use.
3217
3218------------------------
3219"##,
3220 },
3221 Lint {
3222 label: "intra_doc_pointers",
3223 description: r##"# `intra-doc-pointers`
3224
3225The tracking issue for this feature is: [#80896]
3226
3227[#80896]: https://github.com/rust-lang/rust/issues/80896
3228
3229------------------------
3230
3231Rustdoc does not currently allow disambiguating between `*const` and `*mut`, and
3232raw pointers in intra-doc links are unstable until it does.
3233
3234```rust
3235#![feature(intra_doc_pointers)]
3236//! [pointer::add]
3237```
3238"##,
3239 },
3240 Lint {
3241 label: "intrinsics",
3242 description: r##"# `intrinsics`
3243
3244The tracking issue for this feature is: None.
3245
3246Intrinsics are never intended to be stable directly, but intrinsics are often
3247exported in some sort of stable manner. Prefer using the stable interfaces to
3248the intrinsic directly when you can.
3249
3250------------------------
3251
3252
3253These are imported as if they were FFI functions, with the special
3254`rust-intrinsic` ABI. For example, if one was in a freestanding
3255context, but wished to be able to `transmute` between types, and
3256perform efficient pointer arithmetic, one would import those functions
3257via a declaration like
3258
3259```rust
3260#![feature(intrinsics)]
3261# fn main() {}
3262
3263extern "rust-intrinsic" {
3264 fn transmute<T, U>(x: T) -> U;
3265
3266 fn offset<T>(dst: *const T, offset: isize) -> *const T;
3267}
3268```
3269
3270As with any other FFI functions, these are always `unsafe` to call.
3271"##,
3272 },
3273 Lint {
3274 label: "is_sorted",
3275 description: r##"# `is_sorted`
3276
3277The tracking issue for this feature is: [#53485]
3278
3279[#53485]: https://github.com/rust-lang/rust/issues/53485
3280
3281------------------------
3282
3283Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`;
3284add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to
3285`Iterator`.
3286"##,
3287 },
3288 Lint {
3289 label: "lang_items",
3290 description: r##"# `lang_items`
3291
3292The tracking issue for this feature is: None.
3293
3294------------------------
3295
3296The `rustc` compiler has certain pluggable operations, that is,
3297functionality that isn't hard-coded into the language, but is
3298implemented in libraries, with a special marker to tell the compiler
3299it exists. The marker is the attribute `#[lang = "..."]` and there are
3300various different values of `...`, i.e. various different 'lang
33