aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_db/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_db/src')
-rw-r--r--crates/ide_db/src/call_info.rs5
-rw-r--r--crates/ide_db/src/defs.rs10
-rw-r--r--crates/ide_db/src/helpers.rs1
-rw-r--r--crates/ide_db/src/helpers/generated_lints.rs7330
-rw-r--r--crates/ide_db/src/helpers/import_assets.rs4
-rw-r--r--crates/ide_db/src/helpers/insert_use.rs18
-rw-r--r--crates/ide_db/src/helpers/insert_use/tests.rs15
-rw-r--r--crates/ide_db/src/helpers/merge_imports.rs2
-rw-r--r--crates/ide_db/src/lib.rs1
-rw-r--r--crates/ide_db/src/search.rs61
-rw-r--r--crates/ide_db/src/symbol_index.rs2
11 files changed, 7412 insertions, 37 deletions
diff --git a/crates/ide_db/src/call_info.rs b/crates/ide_db/src/call_info.rs
index bad277a95..4795e2565 100644
--- a/crates/ide_db/src/call_info.rs
+++ b/crates/ide_db/src/call_info.rs
@@ -162,7 +162,7 @@ impl ActiveParameter {
162 } 162 }
163 163
164 pub fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> { 164 pub fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> {
165 let (signature, active_parameter) = call_info_impl(&sema, token)?; 165 let (signature, active_parameter) = call_info_impl(sema, token)?;
166 166
167 let idx = active_parameter?; 167 let idx = active_parameter?;
168 let mut params = signature.params(sema.db); 168 let mut params = signature.params(sema.db);
@@ -223,9 +223,8 @@ impl FnCallNode {
223 ast::Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?, 223 ast::Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?,
224 _ => return None, 224 _ => return None,
225 }), 225 }),
226
227 FnCallNode::MethodCallExpr(call_expr) => { 226 FnCallNode::MethodCallExpr(call_expr) => {
228 call_expr.syntax().children().filter_map(ast::NameRef::cast).next() 227 call_expr.syntax().children().find_map(ast::NameRef::cast)
229 } 228 }
230 } 229 }
231 } 230 }
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index 1dcccbb8b..a54f2c323 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -357,9 +357,9 @@ impl NameRefClass {
357 } 357 }
358 } 358 }
359 359
360 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { 360 if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
361 if let Some(path) = macro_call.path() { 361 if path.qualifier().is_none() {
362 if path.qualifier().is_none() { 362 if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
363 // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment 363 // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment
364 // paths are handled below (allowing `log$0::info!` to resolve to the log crate). 364 // paths are handled below (allowing `log$0::info!` to resolve to the log crate).
365 if let Some(macro_def) = sema.resolve_macro_call(&macro_call) { 365 if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {
@@ -367,11 +367,9 @@ impl NameRefClass {
367 } 367 }
368 } 368 }
369 } 369 }
370 }
371 370
372 if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
373 if let Some(resolved) = sema.resolve_path(&path) { 371 if let Some(resolved) = sema.resolve_path(&path) {
374 if path.syntax().parent().and_then(ast::Attr::cast).is_some() { 372 if path.syntax().ancestors().find_map(ast::Attr::cast).is_some() {
375 if let PathResolution::Def(ModuleDef::Function(func)) = resolved { 373 if let PathResolution::Def(ModuleDef::Function(func)) = resolved {
376 if func.attrs(sema.db).by_key("proc_macro_attribute").exists() { 374 if func.attrs(sema.db).by_key("proc_macro_attribute").exists() {
377 return Some(NameRefClass::Definition(resolved.into())); 375 return Some(NameRefClass::Definition(resolved.into()));
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..55438749b
--- /dev/null
+++ b/crates/ide_db/src/helpers/generated_lints.rs
@@ -0,0 +1,7330 @@
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: "fd",
2423 description: r##"# `fd`
2424
2425This feature is internal to the Rust compiler and is not intended for general use.
2426
2427------------------------
2428"##,
2429 },
2430 Lint {
2431 label: "fd_read",
2432 description: r##"# `fd_read`
2433
2434This feature is internal to the Rust compiler and is not intended for general use.
2435
2436------------------------
2437"##,
2438 },
2439 Lint {
2440 label: "ffi_const",
2441 description: r##"# `ffi_const`
2442
2443The tracking issue for this feature is: [#58328]
2444
2445------
2446
2447The `#[ffi_const]` attribute applies clang's `const` attribute to foreign
2448functions declarations.
2449
2450That is, `#[ffi_const]` functions shall have no effects except for its return
2451value, which can only depend on the values of the function parameters, and is
2452not affected by changes to the observable state of the program.
2453
2454Applying the `#[ffi_const]` attribute to a function that violates these
2455requirements is undefined behaviour.
2456
2457This attribute enables Rust to perform common optimizations, like sub-expression
2458elimination, and it can avoid emitting some calls in repeated invocations of the
2459function with the same argument values regardless of other operations being
2460performed in between these functions calls (as opposed to `#[ffi_pure]`
2461functions).
2462
2463## Pitfalls
2464
2465A `#[ffi_const]` function can only read global memory that would not affect
2466its return value for the whole execution of the program (e.g. immutable global
2467memory). `#[ffi_const]` functions are referentially-transparent and therefore
2468more strict than `#[ffi_pure]` functions.
2469
2470A common pitfall involves applying the `#[ffi_const]` attribute to a
2471function that reads memory through pointer arguments which do not necessarily
2472point to immutable global memory.
2473
2474A `#[ffi_const]` function that returns unit has no effect on the abstract
2475machine's state, and a `#[ffi_const]` function cannot be `#[ffi_pure]`.
2476
2477A `#[ffi_const]` function must not diverge, neither via a side effect (e.g. a
2478call to `abort`) nor by infinite loops.
2479
2480When translating C headers to Rust FFI, it is worth verifying for which targets
2481the `const` attribute is enabled in those headers, and using the appropriate
2482`cfg` macros in the Rust side to match those definitions. While the semantics of
2483`const` are implemented identically by many C and C++ compilers, e.g., clang,
2484[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily
2485implemented in this way on all of them. It is therefore also worth verifying
2486that the semantics of the C toolchain used to compile the binary being linked
2487against are compatible with those of the `#[ffi_const]`.
2488
2489[#58328]: https://github.com/rust-lang/rust/issues/58328
2490[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacgigch.html
2491[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute
2492[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_const.htm
2493"##,
2494 },
2495 Lint {
2496 label: "ffi_pure",
2497 description: r##"# `ffi_pure`
2498
2499The tracking issue for this feature is: [#58329]
2500
2501------
2502
2503The `#[ffi_pure]` attribute applies clang's `pure` attribute to foreign
2504functions declarations.
2505
2506That is, `#[ffi_pure]` functions shall have no effects except for its return
2507value, which shall not change across two consecutive function calls with
2508the same parameters.
2509
2510Applying the `#[ffi_pure]` attribute to a function that violates these
2511requirements is undefined behavior.
2512
2513This attribute enables Rust to perform common optimizations, like sub-expression
2514elimination and loop optimizations. Some common examples of pure functions are
2515`strlen` or `memcmp`.
2516
2517These optimizations are only applicable when the compiler can prove that no
2518program state observable by the `#[ffi_pure]` function has changed between calls
2519of the function, which could alter the result. See also the `#[ffi_const]`
2520attribute, which provides stronger guarantees regarding the allowable behavior
2521of a function, enabling further optimization.
2522
2523## Pitfalls
2524
2525A `#[ffi_pure]` function can read global memory through the function
2526parameters (e.g. pointers), globals, etc. `#[ffi_pure]` functions are not
2527referentially-transparent, and are therefore more relaxed than `#[ffi_const]`
2528functions.
2529
2530However, accessing global memory through volatile or atomic reads can violate the
2531requirement that two consecutive function calls shall return the same value.
2532
2533A `pure` function that returns unit has no effect on the abstract machine's
2534state.
2535
2536A `#[ffi_pure]` function must not diverge, neither via a side effect (e.g. a
2537call to `abort`) nor by infinite loops.
2538
2539When translating C headers to Rust FFI, it is worth verifying for which targets
2540the `pure` attribute is enabled in those headers, and using the appropriate
2541`cfg` macros in the Rust side to match those definitions. While the semantics of
2542`pure` are implemented identically by many C and C++ compilers, e.g., clang,
2543[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily
2544implemented in this way on all of them. It is therefore also worth verifying
2545that the semantics of the C toolchain used to compile the binary being linked
2546against are compatible with those of the `#[ffi_pure]`.
2547
2548
2549[#58329]: https://github.com/rust-lang/rust/issues/58329
2550[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacigdac.html
2551[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute
2552[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_pure.htm
2553"##,
2554 },
2555 Lint {
2556 label: "flt2dec",
2557 description: r##"# `flt2dec`
2558
2559This feature is internal to the Rust compiler and is not intended for general use.
2560
2561------------------------
2562"##,
2563 },
2564 Lint {
2565 label: "fmt_internals",
2566 description: r##"# `fmt_internals`
2567
2568This feature is internal to the Rust compiler and is not intended for general use.
2569
2570------------------------
2571"##,
2572 },
2573 Lint {
2574 label: "fn_traits",
2575 description: r##"# `fn_traits`
2576
2577The tracking issue for this feature is [#29625]
2578
2579See Also: [`unboxed_closures`](../language-features/unboxed-closures.md)
2580
2581[#29625]: https://github.com/rust-lang/rust/issues/29625
2582
2583----
2584
2585The `fn_traits` feature allows for implementation of the [`Fn*`] traits
2586for creating custom closure-like types.
2587
2588[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
2589
2590```rust
2591#![feature(unboxed_closures)]
2592#![feature(fn_traits)]
2593
2594struct Adder {
2595 a: u32
2596}
2597
2598impl FnOnce<(u32, )> for Adder {
2599 type Output = u32;
2600 extern "rust-call" fn call_once(self, b: (u32, )) -> Self::Output {
2601 self.a + b.0
2602 }
2603}
2604
2605fn main() {
2606 let adder = Adder { a: 3 };
2607 assert_eq!(adder(2), 5);
2608}
2609```
2610"##,
2611 },
2612 Lint {
2613 label: "format_args_capture",
2614 description: r##"# `format_args_capture`
2615
2616The tracking issue for this feature is: [#67984]
2617
2618[#67984]: https://github.com/rust-lang/rust/issues/67984
2619
2620------------------------
2621
2622Enables `format_args!` (and macros which use `format_args!` in their implementation, such
2623as `format!`, `print!` and `panic!`) to capture variables from the surrounding scope.
2624This avoids the need to pass named parameters when the binding in question
2625already exists in scope.
2626
2627```rust
2628#![feature(format_args_capture)]
2629
2630let (person, species, name) = ("Charlie Brown", "dog", "Snoopy");
2631
2632// captures named argument `person`
2633print!("Hello {person}");
2634
2635// captures named arguments `species` and `name`
2636format!("The {species}'s name is {name}.");
2637```
2638
2639This also works for formatting parameters such as width and precision:
2640
2641```rust
2642#![feature(format_args_capture)]
2643
2644let precision = 2;
2645let s = format!("{:.precision$}", 1.324223);
2646
2647assert_eq!(&s, "1.32");
2648```
2649
2650A non-exhaustive list of macros which benefit from this functionality include:
2651- `format!`
2652- `print!` and `println!`
2653- `eprint!` and `eprintln!`
2654- `write!` and `writeln!`
2655- `panic!`
2656- `unreachable!`
2657- `unimplemented!`
2658- `todo!`
2659- `assert!` and similar
2660- macros in many thirdparty crates, such as `log`
2661"##,
2662 },
2663 Lint {
2664 label: "generators",
2665 description: r##"# `generators`
2666
2667The tracking issue for this feature is: [#43122]
2668
2669[#43122]: https://github.com/rust-lang/rust/issues/43122
2670
2671------------------------
2672
2673The `generators` feature gate in Rust allows you to define generator or
2674coroutine literals. A generator is a "resumable function" that syntactically
2675resembles a closure but compiles to much different semantics in the compiler
2676itself. The primary feature of a generator is that it can be suspended during
2677execution to be resumed at a later date. Generators use the `yield` keyword to
2678"return", and then the caller can `resume` a generator to resume execution just
2679after the `yield` keyword.
2680
2681Generators are an extra-unstable feature in the compiler right now. Added in
2682[RFC 2033] they're mostly intended right now as a information/constraint
2683gathering phase. The intent is that experimentation can happen on the nightly
2684compiler before actual stabilization. A further RFC will be required to
2685stabilize generators/coroutines and will likely contain at least a few small
2686tweaks to the overall design.
2687
2688[RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033
2689
2690A syntactical example of a generator is:
2691
2692```rust
2693#![feature(generators, generator_trait)]
2694
2695use std::ops::{Generator, GeneratorState};
2696use std::pin::Pin;
2697
2698fn main() {
2699 let mut generator = || {
2700 yield 1;
2701 return "foo"
2702 };
2703
2704 match Pin::new(&mut generator).resume(()) {
2705 GeneratorState::Yielded(1) => {}
2706 _ => panic!("unexpected value from resume"),
2707 }
2708 match Pin::new(&mut generator).resume(()) {
2709 GeneratorState::Complete("foo") => {}
2710 _ => panic!("unexpected value from resume"),
2711 }
2712}
2713```
2714
2715Generators are closure-like literals which can contain a `yield` statement. The
2716`yield` statement takes an optional expression of a value to yield out of the
2717generator. All generator literals implement the `Generator` trait in the
2718`std::ops` module. The `Generator` trait has one main method, `resume`, which
2719resumes execution of the generator at the previous suspension point.
2720
2721An example of the control flow of generators is that the following example
2722prints all numbers in order:
2723
2724```rust
2725#![feature(generators, generator_trait)]
2726
2727use std::ops::Generator;
2728use std::pin::Pin;
2729
2730fn main() {
2731 let mut generator = || {
2732 println!("2");
2733 yield;
2734 println!("4");
2735 };
2736
2737 println!("1");
2738 Pin::new(&mut generator).resume(());
2739 println!("3");
2740 Pin::new(&mut generator).resume(());
2741 println!("5");
2742}
2743```
2744
2745At this time the main intended use case of generators is an implementation
2746primitive for async/await syntax, but generators will likely be extended to
2747ergonomic implementations of iterators and other primitives in the future.
2748Feedback on the design and usage is always appreciated!
2749
2750### The `Generator` trait
2751
2752The `Generator` trait in `std::ops` currently looks like:
2753
2754```rust
2755# #![feature(arbitrary_self_types, generator_trait)]
2756# use std::ops::GeneratorState;
2757# use std::pin::Pin;
2758
2759pub trait Generator<R = ()> {
2760 type Yield;
2761 type Return;
2762 fn resume(self: Pin<&mut Self>, resume: R) -> GeneratorState<Self::Yield, Self::Return>;
2763}
2764```
2765
2766The `Generator::Yield` type is the type of values that can be yielded with the
2767`yield` statement. The `Generator::Return` type is the returned type of the
2768generator. This is typically the last expression in a generator's definition or
2769any value passed to `return` in a generator. The `resume` function is the entry
2770point for executing the `Generator` itself.
2771
2772The return value of `resume`, `GeneratorState`, looks like:
2773
2774```rust
2775pub enum GeneratorState<Y, R> {
2776 Yielded(Y),
2777 Complete(R),
2778}
2779```
2780
2781The `Yielded` variant indicates that the generator can later be resumed. This
2782corresponds to a `yield` point in a generator. The `Complete` variant indicates
2783that the generator is complete and cannot be resumed again. Calling `resume`
2784after a generator has returned `Complete` will likely result in a panic of the
2785program.
2786
2787### Closure-like semantics
2788
2789The closure-like syntax for generators alludes to the fact that they also have
2790closure-like semantics. Namely:
2791
2792* When created, a generator executes no code. A closure literal does not
2793 actually execute any of the closure's code on construction, and similarly a
2794 generator literal does not execute any code inside the generator when
2795 constructed.
2796
2797* Generators can capture outer variables by reference or by move, and this can
2798 be tweaked with the `move` keyword at the beginning of the closure. Like
2799 closures all generators will have an implicit environment which is inferred by
2800 the compiler. Outer variables can be moved into a generator for use as the
2801 generator progresses.
2802
2803* Generator literals produce a value with a unique type which implements the
2804 `std::ops::Generator` trait. This allows actual execution of the generator
2805 through the `Generator::resume` method as well as also naming it in return
2806 types and such.
2807
2808* Traits like `Send` and `Sync` are automatically implemented for a `Generator`
2809 depending on the captured variables of the environment. Unlike closures,
2810 generators also depend on variables live across suspension points. This means
2811 that although the ambient environment may be `Send` or `Sync`, the generator
2812 itself may not be due to internal variables live across `yield` points being
2813 not-`Send` or not-`Sync`. Note that generators do
2814 not implement traits like `Copy` or `Clone` automatically.
2815
2816* Whenever a generator is dropped it will drop all captured environment
2817 variables.
2818
2819### Generators as state machines
2820
2821In the compiler, generators are currently compiled as state machines. Each
2822`yield` expression will correspond to a different state that stores all live
2823variables over that suspension point. Resumption of a generator will dispatch on
2824the current state and then execute internally until a `yield` is reached, at
2825which point all state is saved off in the generator and a value is returned.
2826
2827Let's take a look at an example to see what's going on here:
2828
2829```rust
2830#![feature(generators, generator_trait)]
2831
2832use std::ops::Generator;
2833use std::pin::Pin;
2834
2835fn main() {
2836 let ret = "foo";
2837 let mut generator = move || {
2838 yield 1;
2839 return ret
2840 };
2841
2842 Pin::new(&mut generator).resume(());
2843 Pin::new(&mut generator).resume(());
2844}
2845```
2846
2847This generator literal will compile down to something similar to:
2848
2849```rust
2850#![feature(arbitrary_self_types, generators, generator_trait)]
2851
2852use std::ops::{Generator, GeneratorState};
2853use std::pin::Pin;
2854
2855fn main() {
2856 let ret = "foo";
2857 let mut generator = {
2858 enum __Generator {
2859 Start(&'static str),
2860 Yield1(&'static str),
2861 Done,
2862 }
2863
2864 impl Generator for __Generator {
2865 type Yield = i32;
2866 type Return = &'static str;
2867
2868 fn resume(mut self: Pin<&mut Self>, resume: ()) -> GeneratorState<i32, &'static str> {
2869 use std::mem;
2870 match mem::replace(&mut *self, __Generator::Done) {
2871 __Generator::Start(s) => {
2872 *self = __Generator::Yield1(s);
2873 GeneratorState::Yielded(1)
2874 }
2875
2876 __Generator::Yield1(s) => {
2877 *self = __Generator::Done;
2878 GeneratorState::Complete(s)
2879 }
2880
2881 __Generator::Done => {
2882 panic!("generator resumed after completion")
2883 }
2884 }
2885 }
2886 }
2887
2888 __Generator::Start(ret)
2889 };
2890
2891 Pin::new(&mut generator).resume(());
2892 Pin::new(&mut generator).resume(());
2893}
2894```
2895
2896Notably here we can see that the compiler is generating a fresh type,
2897`__Generator` in this case. This type has a number of states (represented here
2898as an `enum`) corresponding to each of the conceptual states of the generator.
2899At the beginning we're closing over our outer variable `foo` and then that
2900variable is also live over the `yield` point, so it's stored in both states.
2901
2902When the generator starts it'll immediately yield 1, but it saves off its state
2903just before it does so indicating that it has reached the yield point. Upon
2904resuming again we'll execute the `return ret` which returns the `Complete`
2905state.
2906
2907Here we can also note that the `Done` state, if resumed, panics immediately as
2908it's invalid to resume a completed generator. It's also worth noting that this
2909is just a rough desugaring, not a normative specification for what the compiler
2910does.
2911"##,
2912 },
2913 Lint {
2914 label: "global_asm",
2915 description: r##"# `global_asm`
2916
2917The tracking issue for this feature is: [#35119]
2918
2919[#35119]: https://github.com/rust-lang/rust/issues/35119
2920
2921------------------------
2922
2923The `global_asm!` macro allows the programmer to write arbitrary
2924assembly outside the scope of a function body, passing it through
2925`rustc` and `llvm` to the assembler. That is to say, `global_asm!` is
2926equivalent to assembling the asm with an external assembler and then
2927linking the resulting object file with the current crate.
2928
2929`global_asm!` fills a role not currently satisfied by either `asm!`
2930or `#[naked]` functions. The programmer has _all_ features of the
2931assembler at their disposal. The linker will expect to resolve any
2932symbols defined in the inline assembly, modulo any symbols marked as
2933external. It also means syntax for directives and assembly follow the
2934conventions of the assembler in your toolchain.
2935
2936A simple usage looks like this:
2937
2938```rust,ignore (requires-external-file)
2939#![feature(global_asm)]
2940# // you also need relevant target_arch cfgs
2941global_asm!(include_str!("something_neato.s"));
2942```
2943
2944And a more complicated usage looks like this:
2945
2946```rust,no_run
2947#![feature(global_asm)]
2948# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
2949# mod x86 {
2950
2951pub mod sally {
2952 global_asm!(
2953 ".global foo",
2954 "foo:",
2955 "jmp baz",
2956 );
2957
2958 #[no_mangle]
2959 pub unsafe extern "C" fn baz() {}
2960}
2961
2962// the symbols `foo` and `bar` are global, no matter where
2963// `global_asm!` was used.
2964extern "C" {
2965 fn foo();
2966 fn bar();
2967}
2968
2969pub mod harry {
2970 global_asm!(
2971 ".global bar",
2972 "bar:",
2973 "jmp quux",
2974 );
2975
2976 #[no_mangle]
2977 pub unsafe extern "C" fn quux() {}
2978}
2979# }
2980```
2981
2982You may use `global_asm!` multiple times, anywhere in your crate, in
2983whatever way suits you. However, you should not rely on assembler state
2984(e.g. assembler macros) defined in one `global_asm!` to be available in
2985another one. It is implementation-defined whether the multiple usages
2986are concatenated into one or assembled separately.
2987
2988`global_asm!` also supports `const` operands like `asm!`, which allows
2989constants defined in Rust to be used in assembly code:
2990
2991```rust,no_run
2992#![feature(global_asm)]
2993# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
2994# mod x86 {
2995const C: i32 = 1234;
2996global_asm!(
2997 ".global bar",
2998 "bar: .word {c}",
2999 c = const C,
3000);
3001# }
3002```
3003
3004The syntax for passing operands is the same as `asm!` except that only
3005`const` operands are allowed. Refer to the [asm](asm.md) documentation
3006for more details.
3007
3008On x86, the assembly code will use intel syntax by default. You can
3009override this by adding `options(att_syntax)` at the end of the macro
3010arguments list:
3011
3012```rust,no_run
3013#![feature(global_asm)]
3014# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
3015# mod x86 {
3016global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
3017// is equivalent to
3018global_asm!("mov ecx, {}", const 5);
3019# }
3020```
3021
3022------------------------
3023
3024If you don't need quite as much power and flexibility as
3025`global_asm!` provides, and you don't mind restricting your inline
3026assembly to `fn` bodies only, you might try the
3027[asm](asm.md) feature instead.
3028"##,
3029 },
3030 Lint {
3031 label: "impl_trait_in_bindings",
3032 description: r##"# `impl_trait_in_bindings`
3033
3034The tracking issue for this feature is: [#63065]
3035
3036[#63065]: https://github.com/rust-lang/rust/issues/63065
3037
3038------------------------
3039
3040The `impl_trait_in_bindings` feature gate lets you use `impl Trait` syntax in
3041`let`, `static`, and `const` bindings.
3042
3043A simple example is:
3044
3045```rust
3046#![feature(impl_trait_in_bindings)]
3047
3048use std::fmt::Debug;
3049
3050fn main() {
3051 let a: impl Debug + Clone = 42;
3052 let b = a.clone();
3053 println!("{:?}", b); // prints `42`
3054}
3055```
3056
3057Note however that because the types of `a` and `b` are opaque in the above
3058example, calling inherent methods or methods outside of the specified traits
3059(e.g., `a.abs()` or `b.abs()`) is not allowed, and yields an error.
3060"##,
3061 },
3062 Lint {
3063 label: "infer_static_outlives_requirements",
3064 description: r##"# `infer_static_outlives_requirements`
3065
3066The tracking issue for this feature is: [#54185]
3067
3068[#54185]: https://github.com/rust-lang/rust/issues/54185
3069
3070------------------------
3071The `infer_static_outlives_requirements` feature indicates that certain
3072`'static` outlives requirements can be inferred by the compiler rather than
3073stating them explicitly.
3074
3075Note: It is an accompanying feature to `infer_outlives_requirements`,
3076which must be enabled to infer outlives requirements.
3077
3078For example, currently generic struct definitions that contain
3079references, require where-clauses of the form T: 'static. By using
3080this feature the outlives predicates will be inferred, although
3081they may still be written explicitly.
3082
3083```rust,ignore (pseudo-Rust)
3084struct Foo<U> where U: 'static { // <-- currently required
3085 bar: Bar<U>
3086}
3087struct Bar<T: 'static> {
3088 x: T,
3089}
3090```
3091
3092
3093## Examples:
3094
3095```rust,ignore (pseudo-Rust)
3096#![feature(infer_outlives_requirements)]
3097#![feature(infer_static_outlives_requirements)]
3098
3099#[rustc_outlives]
3100// Implicitly infer U: 'static
3101struct Foo<U> {
3102 bar: Bar<U>
3103}
3104struct Bar<T: 'static> {
3105 x: T,
3106}
3107```
3108"##,
3109 },
3110 Lint {
3111 label: "inline_const",
3112 description: r##"# `inline_const`
3113
3114The tracking issue for this feature is: [#76001]
3115
3116------
3117
3118This feature allows you to use inline constant expressions. For example, you can
3119turn this code:
3120
3121```rust
3122# fn add_one(x: i32) -> i32 { x + 1 }
3123const MY_COMPUTATION: i32 = 1 + 2 * 3 / 4;
3124
3125fn main() {
3126 let x = add_one(MY_COMPUTATION);
3127}
3128```
3129
3130into this code:
3131
3132```rust
3133#![feature(inline_const)]
3134
3135# fn add_one(x: i32) -> i32 { x + 1 }
3136fn main() {
3137 let x = add_one(const { 1 + 2 * 3 / 4 });
3138}
3139```
3140
3141You can also use inline constant expressions in patterns:
3142
3143```rust
3144#![feature(inline_const)]
3145
3146const fn one() -> i32 { 1 }
3147
3148let some_int = 3;
3149match some_int {
3150 const { 1 + 2 } => println!("Matched 1 + 2"),
3151 const { one() } => println!("Matched const fn returning 1"),
3152 _ => println!("Didn't match anything :("),
3153}
3154```
3155
3156[#76001]: https://github.com/rust-lang/rust/issues/76001
3157"##,
3158 },
3159 Lint {
3160 label: "int_error_internals",
3161 description: r##"# `int_error_internals`
3162
3163This feature is internal to the Rust compiler and is not intended for general use.
3164
3165------------------------
3166"##,
3167 },
3168 Lint {
3169 label: "internal_output_capture",
3170 description: r##"# `internal_output_capture`
3171
3172This feature is internal to the Rust compiler and is not intended for general use.
3173
3174------------------------
3175"##,
3176 },
3177 Lint {
3178 label: "intra_doc_pointers",
3179 description: r##"# `intra-doc-pointers`
3180
3181The tracking issue for this feature is: [#80896]
3182
3183[#80896]: https://github.com/rust-lang/rust/issues/80896
3184
3185------------------------
3186
3187Rustdoc does not currently allow disambiguating between `*const` and `*mut`, and
3188raw pointers in intra-doc links are unstable until it does.
3189
3190```rust
3191#![feature(intra_doc_pointers)]
3192//! [pointer::add]
3193```
3194"##,
3195 },
3196 Lint {
3197 label: "intrinsics",
3198 description: r##"# `intrinsics`
3199
3200The tracking issue for this feature is: None.
3201
3202Intrinsics are never intended to be stable directly, but intrinsics are often
3203exported in some sort of stable manner. Prefer using the stable interfaces to
3204the intrinsic directly when you can.
3205
3206------------------------
3207
3208
3209These are imported as if they were FFI functions, with the special
3210`rust-intrinsic` ABI. For example, if one was in a freestanding
3211context, but wished to be able to `transmute` between types, and
3212perform efficient pointer arithmetic, one would import those functions
3213via a declaration like
3214
3215```rust
3216#![feature(intrinsics)]
3217# fn main() {}
3218
3219extern "rust-intrinsic" {
3220 fn transmute<T, U>(x: T) -> U;
3221
3222 fn offset<T>(dst: *const T, offset: isize) -> *const T;
3223}
3224```
3225