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
3226As with any other FFI functions, these are always `unsafe` to call.
3227"##,
3228 },
3229 Lint {
3230 label: "is_sorted",
3231 description: r##"# `is_sorted`
3232
3233The tracking issue for this feature is: [#53485]
3234
3235[#53485]: https://github.com/rust-lang/rust/issues/53485
3236
3237------------------------
3238
3239Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`;
3240add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to
3241`Iterator`.
3242"##,
3243 },
3244 Lint {
3245 label: "lang_items",
3246 description: r##"# `lang_items`
3247
3248The tracking issue for this feature is: None.
3249
3250------------------------
3251
3252The `rustc` compiler has certain pluggable operations, that is,
3253functionality that isn't hard-coded into the language, but is
3254implemented in libraries, with a special marker to tell the compiler
3255it exists. The marker is the attribute `#[lang = "..."]` and there are
3256various different values of `...`, i.e. various different 'lang
3257items'.
3258
3259For example, `Box` pointers require two lang items, one for allocation
3260and one for deallocation. A freestanding program that uses the `Box`
3261sugar for dynamic allocations via `malloc` and `free`:
3262
3263```rust,ignore (libc-is-finicky)
3264#![feature(lang_items, box_syntax, start, libc, core_intrinsics, rustc_private)]
3265#![no_std]
3266use core::intrinsics;
3267use core::panic::PanicInfo;
3268
3269extern crate libc;
3270
3271#[lang = "owned_box"]
3272pub struct Box<T>(*mut T);
3273
3274#[lang = "exchange_malloc"]
3275unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
3276 let p = libc::malloc(size as libc::size_t) as *mut u8;
3277
3278 // Check if `malloc` failed:
3279 if p as usize == 0 {
3280 intrinsics::abort();
3281 }
3282
3283 p
3284}
3285
3286#[lang = "box_free"]
3287unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
3288 libc::free(ptr as *mut libc::c_void)
3289}
3290
3291#[start]
3292fn main(_argc: isize, _argv: *const *const u8) -> isize {
3293 let _x = box 1;
3294
3295 0
3296}
3297
3298#[lang = "eh_personality"] extern fn rust_eh_personality() {}
3299#[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } }
3300#[no_mangle] pub extern fn rust_eh_register_frames () {}
3301#[no_mangle] pub extern fn rust_eh_unregister_frames () {}
3302```
3303
3304Note the use of `abort`: the `exchange_malloc` lang item is assumed to
3305return a valid pointer, and so needs to do the check internally.
3306
3307Other features provided by lang items include:
3308
3309- overloadable operators via traits: the traits corresponding to the
3310 `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
3311 marked with lang items; those specific four are `eq`, `ord`,
3312 `deref`, and `add` respectively.
3313- stack unwinding and general failure; the `eh_personality`,
3314 `panic` and `panic_bounds_check` lang items.
3315- the traits in `std::marker` used to indicate types of
3316 various kinds; lang items `send`, `sync` and `copy`.
3317- the marker types and variance indicators found in
3318 `std::marker`; lang items `covariant_type`,
3319 `contravariant_lifetime`, etc.
3320
3321Lang items are loaded lazily by the compiler; e.g. if one never uses
3322`Box` then there is no need to define functions for `exchange_malloc`
3323and `box_free`. `rustc` will emit an error when an item is needed
3324but not found in the current crate or any that it depends on.
3325
3326Most lang items are defined by `libcore`, but if you're trying to build
3327an executable without the standard library, you'll run into the need
3328for lang items. The rest of this page focuses on this use-case, even though
3329lang items are a bit broader than that.
3330
3331### Using libc
3332
3333In order to build a `#[no_std]` executable we will need libc as a dependency.
3334We can specify this using our `Cargo.toml` file:
3335
3336```toml
3337[dependencies]
3338libc = { version = "0.2.14", default-features = false }
3339```
3340
3341Note that the default features have been disabled. This is a critical step -
3342**the default features of libc include the standard library and so must be
3343disabled.**
3344
3345### Writing an executable without stdlib
3346
3347Controlling the entry point is possible in two ways: the `#[start]` attribute,
3348or overriding the default shim for the C `main` function with your own.
3349
3350The function marked `#[start]` is passed the command line parameters
3351in the same format as C:
3352
3353```rust,ignore (libc-is-finicky)
3354#![feature(lang_items, core_intrinsics, rustc_private)]
3355#![feature(start)]
3356#![no_std]
3357use core::intrinsics;
3358use core::panic::PanicInfo;
3359
3360// Pull in the system libc library for what crt0.o likely requires.
3361extern crate libc;
3362
3363// Entry point for this program.
3364#[start]
3365fn start(_argc: isize, _argv: *const *const u8) -> isize {
3366 0
3367}
3368
3369// These functions are used by the compiler, but not
3370// for a bare-bones hello world. These are normally
3371// provided by libstd.
3372#[lang = "eh_personality"]
3373#[no_mangle]
3374pub extern fn rust_eh_personality() {
3375}
3376
3377#[lang = "panic_impl"]
3378#[no_mangle]
3379pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
3380 unsafe { intrinsics::abort() }
3381}
3382```
3383
3384To override the compiler-inserted `main` shim, one has to disable it
3385with `#![no_main]` and then create the appropriate symbol with the
3386correct ABI and the correct name, which requires overriding the
3387compiler's name mangling too:
3388
3389```rust,ignore (libc-is-finicky)
3390#![feature(lang_items, core_intrinsics, rustc_private)]
3391#![feature(start)]
3392#![no_std]
3393#![no_main]
3394use core::intrinsics;
3395use core::panic::PanicInfo;
3396
3397// Pull in the system libc library for what crt0.o likely requires.
3398extern crate libc;
3399
3400// Entry point for this program.
3401#[no_mangle] // ensure that this symbol is called `main` in the output
3402pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
3403 0
3404}
3405
3406// These functions are used by the compiler, but not
3407// for a bare-bones hello world. These are normally
3408// provided by libstd.
3409#[lang = "eh_personality"]
3410#[no_mangle]
3411pub extern fn rust_eh_personality() {
3412}
3413
3414#[lang = "panic_impl"]
3415#[no_mangle]
3416pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
3417 unsafe { intrinsics::abort() }
3418}
3419```
3420
3421In many cases, you may need to manually link to the `compiler_builtins` crate
3422when building a `no_std` binary. You may observe this via linker error messages
3423such as "```undefined reference to `__rust_probestack'```".
3424
3425## More about the language items
3426
3427The compiler currently makes a few assumptions about symbols which are
3428available in the executable to call. Normally these functions are provided by
3429the standard library, but without it you must define your own. These symbols
3430are called "language items", and they each have an internal name, and then a
3431signature that an implementation must conform to.
3432
3433The first of these functions, `rust_eh_personality`, is used by the failure
3434mechanisms of the compiler. This is often mapped to GCC's personality function
3435(see the [libstd implementation][unwind] for more information), but crates
3436which do not trigger a panic can be assured that this function is never
3437called. The language item's name is `eh_personality`.
3438
3439[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs
3440
3441The second function, `rust_begin_panic`, is also used by the failure mechanisms of the
3442compiler. When a panic happens, this controls the message that's displayed on
3443the screen. While the language item's name is `panic_impl`, the symbol name is
3444`rust_begin_panic`.
3445
3446Finally, a `eh_catch_typeinfo` static is needed for certain targets which
3447implement Rust panics on top of C++ exceptions.
3448
3449## List of all language items
3450
3451This is a list of all language items in Rust along with where they are located in
3452the source code.
3453
3454- Primitives
3455 - `i8`: `libcore/num/mod.rs`
3456 - `i16`: `libcore/num/mod.rs`
3457 - `i32`: `libcore/num/mod.rs`
3458 - `i64`: `libcore/num/mod.rs`
3459 - `i128`: `libcore/num/mod.rs`
3460 - `isize`: `libcore/num/mod.rs`
3461 - `u8`: `libcore/num/mod.rs`
3462 - `u16`: `libcore/num/mod.rs`
3463 - `u32`: `libcore/num/mod.rs`
3464 - `u64`: `libcore/num/mod.rs`
3465 - `u128`: `libcore/num/mod.rs`
3466 - `usize`: `libcore/num/mod.rs`
3467 - `f32`: `libstd/f32.rs`
3468 - `f64`: `libstd/f64.rs`
3469 - `char`: `libcore/char.rs`
3470 - `slice`: `liballoc/slice.rs`
3471 - `str`: `liballoc/str.rs`
3472 - `const_ptr`: `libcore/ptr.rs`
3473 - `mut_ptr`: `libcore/ptr.rs`
3474 - `unsafe_cell`: `libcore/cell.rs`
3475- Runtime
3476 - `start`: `libstd/rt.rs`
3477 - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC)
3478 - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU)
3479 - `eh_personality`: `libpanic_unwind/seh.rs` (SEH)
3480 - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC)
3481 - `panic`: `libcore/panicking.rs`
3482 - `panic_bounds_check`: `libcore/panicking.rs`
3483 - `panic_impl`: `libcore/panicking.rs`
3484 - `panic_impl`: `libstd/panicking.rs`
3485- Allocations
3486 - `owned_box`: `liballoc/boxed.rs`
3487 - `exchange_malloc`: `liballoc/heap.rs`
3488 - `box_free`: `liballoc/heap.rs`
3489- Operands
3490 - `not`: `libcore/ops/bit.rs`
3491 - `bitand`: `libcore/ops/bit.rs`
3492 - `bitor`: `libcore/ops/bit.rs`
3493 - `bitxor`: `libcore/ops/bit.rs`
3494 - `shl`: `libcore/ops/bit.rs`
3495 - `shr`: `libcore/ops/bit.rs`
3496 - `bitand_assign`: `libcore/ops/bit.rs`
3497 - `bitor_assign`: `libcore/ops/bit.rs`
3498 - `bitxor_assign`: `libcore/ops/bit.rs`
3499 - `shl_assign`: `libcore/ops/bit.rs`
3500 - `shr_assign`: `libcore/ops/bit.rs`
3501 - `deref`: `libcore/ops/deref.rs`
3502 - `deref_mut`: `libcore/ops/deref.rs`
3503 - `index`: `libcore/ops/index.rs`
3504 - `index_mut`: `libcore/ops/index.rs`
3505 - `add`: `libcore/ops/arith.rs`
3506 - `sub`: `libcore/ops/arith.rs`
3507 - `mul`: `libcore/ops/arith.rs`
3508 - `div`: `libcore/ops/arith.rs`
3509 - `rem`: `libcore/ops/arith.rs`
3510 - `neg`: `libcore/ops/arith.rs`
3511 - `add_assign`: `libcore/ops/arith.rs`
3512 - `sub_assign`: `libcore/ops/arith.rs`
3513 - `mul_assign`: `libcore/ops/arith.rs`
3514 - `div_assign`: `libcore/ops/arith.rs`
3515 - `rem_assign`: `libcore/ops/arith.rs`
3516 - `eq`: `libcore/cmp.rs`
3517 - `ord`: `libcore/cmp.rs`
3518- Functions
3519 - `fn`: `libcore/ops/function.rs`
3520 - `fn_mut`: `libcore/ops/function.rs`
3521 - `fn_once`: `libcore/ops/function.rs`
3522 - `generator_state`: `libcore/ops/generator.rs`
3523 - `generator`: `libcore/ops/generator.rs`
3524- Other
3525 - `coerce_unsized`: `libcore/ops/unsize.rs`
3526 - `drop`: `libcore/ops/drop.rs`
3527 - `drop_in_place`: `libcore/ptr.rs`
3528 - `clone`: `libcore/clone.rs`
3529 - `copy`: `libcore/marker.rs`
3530 - `send`: `libcore/marker.rs`
3531 - `sized`: `libcore/marker.rs`
3532 - `unsize`: `libcore/marker.rs`
3533 - `sync`: `libcore/marker.rs`
3534 - `phantom_data`: `libcore/marker.rs`
3535 - `discriminant_kind`: `libcore/marker.rs`
3536 - `freeze`: `libcore/marker.rs`
3537 - `debug_trait`: `libcore/fmt/mod.rs`
3538 - `non_zero`: `libcore/nonzero.rs`
3539 - `arc`: `liballoc/sync.rs`
3540 - `rc`: `liballoc/rc.rs`
3541"##,
3542 },
3543 Lint {
3544 label: "libstd_sys_internals",
3545 description: r##"# `libstd_sys_internals`
3546
3547This feature is internal to the Rust compiler and is not intended for general use.
3548
3549------------------------
3550"##,
3551 },
3552 Lint {
3553 label: "libstd_thread_internals",
3554 description: r##"# `libstd_thread_internals`
3555
3556This feature is internal to the Rust compiler and is not intended for general use.
3557
3558------------------------
3559"##,
3560 },
3561 Lint {
3562 label: "link_cfg",
3563 description: r##"# `link_cfg`
3564
3565This feature is internal to the Rust compiler and is not intended for general use.
3566
3567------------------------
3568"##,
3569 },
3570 Lint {
3571 label: "llvm_asm",
3572 description: r##"# `llvm_asm`
3573
3574The tracking issue for this feature is: [#70173]
3575
3576[#70173]: https://github.com/rust-lang/rust/issues/70173
3577
3578------------------------
3579
3580For extremely low-level manipulations and performance reasons, one
3581might wish to control the CPU directly. Rust supports using inline
3582assembly to do this via the `llvm_asm!` macro.
3583
3584```rust,ignore (pseudo-code)
3585llvm_asm!(assembly template
3586 : output operands
3587 : input operands
3588 : clobbers
3589 : options
3590 );
3591```
3592
3593Any use of `llvm_asm` is feature gated (requires `#![feature(llvm_asm)]` on the
3594crate to allow) and of course requires an `unsafe` block.
3595
3596> **Note**: the examples here are given in x86/x86-64 assembly, but
3597> all platforms are supported.
3598
3599## Assembly template
3600
3601The `assembly template` is the only required parameter and must be a
3602literal string (i.e. `""`)
3603
3604```rust
3605#![feature(llvm_asm)]
3606
3607#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3608fn foo() {
3609 unsafe {
3610 llvm_asm!("NOP");
3611 }
3612}
3613
3614// Other platforms:
3615#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
3616fn foo() { /* ... */ }
3617
3618fn main() {
3619 // ...
3620 foo();
3621 // ...
3622}
3623```
3624
3625(The `feature(llvm_asm)` and `#[cfg]`s are omitted from now on.)
3626
3627Output operands, input operands, clobbers and options are all optional
3628but you must add the right number of `:` if you skip them:
3629
3630```rust
3631# #![feature(llvm_asm)]
3632# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3633# fn main() { unsafe {
3634llvm_asm!("xor %eax, %eax"
3635 :
3636 :
3637 : "eax"
3638 );
3639# } }
3640# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
3641# fn main() {}
3642```
3643
3644Whitespace also doesn't matter:
3645
3646```rust
3647# #![feature(llvm_asm)]
3648# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3649# fn main() { unsafe {
3650llvm_asm!("xor %eax, %eax" ::: "eax");
3651# } }
3652# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
3653# fn main() {}
3654```
3655
3656## Operands
3657
3658Input and output operands follow the same format: `:
3659"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand
3660expressions must be mutable place, or not yet assigned:
3661
3662```rust
3663# #![feature(llvm_asm)]
3664# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3665fn add(a: i32, b: i32) -> i32 {
3666 let c: i32;
3667 unsafe {
3668 llvm_asm!("add $2, $0"
3669 : "=r"(c)
3670 : "0"(a), "r"(b)
3671 );
3672 }
3673 c
3674}
3675# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
3676# fn add(a: i32, b: i32) -> i32 { a + b }
3677
3678fn main() {
3679 assert_eq!(add(3, 14159), 14162)
3680}
3681```
3682
3683If you would like to use real operands in this position, however,
3684you are required to put curly braces `{}` around the register that
3685you want, and you are required to put the specific size of the
3686operand. This is useful for very low level programming, where
3687which register you use is important:
3688
3689```rust
3690# #![feature(llvm_asm)]
3691# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3692# unsafe fn read_byte_in(port: u16) -> u8 {
3693let result: u8;
3694llvm_asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port));
3695result
3696# }
3697```
3698
3699## Clobbers
3700
3701Some instructions modify registers which might otherwise have held
3702different values so we use the clobbers list to indicate to the
3703compiler not to assume any values loaded into those registers will
3704stay valid.
3705
3706```rust
3707# #![feature(llvm_asm)]
3708# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3709# fn main() { unsafe {
3710// Put the value 0x200 in eax:
3711llvm_asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax");
3712# } }
3713# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
3714# fn main() {}
3715```
3716
3717Input and output registers need not be listed since that information
3718is already communicated by the given constraints. Otherwise, any other
3719registers used either implicitly or explicitly should be listed.
3720
3721If the assembly changes the condition code register `cc` should be
3722specified as one of the clobbers. Similarly, if the assembly modifies
3723memory, `memory` should also be specified.
3724
3725## Options
3726
3727The last section, `options` is specific to Rust. The format is comma
3728separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to
3729specify some extra info about the inline assembly:
3730
3731Current valid options are:
3732
37331. `volatile` - specifying this is analogous to
3734 `__asm__ __volatile__ (...)` in gcc/clang.
37352. `alignstack` - certain instructions expect the stack to be
3736 aligned a certain way (i.e. SSE) and specifying this indicates to
3737 the compiler to insert its usual stack alignment code
37383. `intel` - use intel syntax instead of the default AT&T.
3739
3740```rust
3741# #![feature(llvm_asm)]
3742# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3743# fn main() {
3744let result: i32;
3745unsafe {
3746 llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
3747}
3748println!("eax is currently {}", result);
3749# }
3750# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
3751# fn main() {}
3752```
3753
3754## More Information
3755
3756The current implementation of the `llvm_asm!` macro is a direct binding to [LLVM's
3757inline assembler expressions][llvm-docs], so be sure to check out [their
3758documentation as well][llvm-docs] for more information about clobbers,
3759constraints, etc.
3760
3761[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
3762
3763If you need more power and don't mind losing some of the niceties of
3764`llvm_asm!`, check out [global_asm](global-asm.md).
3765"##,
3766 },
3767 Lint {
3768 label: "marker_trait_attr",
3769 description: r##"# `marker_trait_attr`
3770
3771The tracking issue for this feature is: [#29864]
3772
3773[#29864]: https://github.com/rust-lang/rust/issues/29864
3774
3775------------------------
3776
3777Normally, Rust keeps you from adding trait implementations that could
3778overlap with each other, as it would be ambiguous which to use. This
3779feature, however, carves out an exception to that rule: a trait can
3780opt-in to having overlapping implementations, at the cost that those
3781implementations are not allowed to override anything (and thus the
3782trait itself cannot have any associated items, as they're pointless
3783when they'd need to do the same thing for every type anyway).
3784
3785```rust
3786#![feature(marker_trait_attr)]
3787
3788#[marker] trait CheapToClone: Clone {}
3789
3790impl<T: Copy> CheapToClone for T {}
3791
3792// These could potentially overlap with the blanket implementation above,
3793// so are only allowed because CheapToClone is a marker trait.
3794impl<T: CheapToClone, U: CheapToClone> CheapToClone for (T, U) {}
3795impl<T: CheapToClone> CheapToClone for std::ops::Range<T> {}
3796
3797fn cheap_clone<T: CheapToClone>(t: T) -> T {
3798 t.clone()
3799}
3800```
3801
3802This is expected to replace the unstable `overlapping_marker_traits`
3803feature, which applied to all empty traits (without needing an opt-in).
3804"##,
3805 },
3806 Lint {
3807 label: "native_link_modifiers",
3808 description: r##"# `native_link_modifiers`
3809
3810The tracking issue for this feature is: [#81490]
3811
3812[#81490]: https://github.com/rust-lang/rust/issues/81490
3813
3814------------------------
3815
3816The `native_link_modifiers` feature allows you to use the `modifiers` syntax with the `#[link(..)]` attribute.
3817
3818Modifiers are specified as a comma-delimited string with each modifier prefixed with either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively. The last boolean value specified for a given modifier wins.
3819"##,
3820 },
3821 Lint {
3822 label: "native_link_modifiers_as_needed",
3823 description: r##"# `native_link_modifiers_as_needed`
3824
3825The tracking issue for this feature is: [#81490]
3826
3827[#81490]: https://github.com/rust-lang/rust/issues/81490
3828
3829------------------------
3830
3831The `native_link_modifiers_as_needed` feature allows you to use the `as-needed` modifier.
3832
3833`as-needed` is only compatible with the `dynamic` and `framework` linking kinds. Using any other kind will result in a compiler error.
3834
3835`+as-needed` means that the library will be actually linked only if it satisfies some undefined symbols at the point at which it is specified on the command line, making it similar to static libraries in this regard.
3836
3837This modifier translates to `--as-needed` for ld-like linkers, and to `-dead_strip_dylibs` / `-needed_library` / `-needed_framework` for ld64.
3838The modifier does nothing for linkers that don't support it (e.g. `link.exe`).
3839
3840The default for this modifier is unclear, some targets currently specify it as `+as-needed`, some do not. We may want to try making `+as-needed` a default for all targets.
3841"##,
3842 },
3843 Lint {
3844 label: "native_link_modifiers_bundle",
3845 description: r##"# `native_link_modifiers_bundle`
3846
3847The tracking issue for this feature is: [#81490]
3848
3849[#81490]: https://github.com/rust-lang/rust/issues/81490
3850
3851------------------------
3852
3853The `native_link_modifiers_bundle` feature allows you to use the `bundle` modifier.
3854
3855Only compatible with the `static` linking kind. Using any other kind will result in a compiler error.
3856
3857`+bundle` means objects from the static library are bundled into the produced crate (a rlib, for example) and are used from this crate later during linking of the final binary.
3858
3859`-bundle` means the static library is included into the produced rlib "by name" and object files from it are included only during linking of the final binary, the file search by that name is also performed during final linking.
3860
3861This modifier is supposed to supersede the `static-nobundle` linking kind defined by [RFC 1717](https://github.com/rust-lang/rfcs/pull/1717).
3862
3863The default for this modifier is currently `+bundle`, but it could be changed later on some future edition boundary.
3864"##,
3865 },
3866 Lint {
3867 label: "native_link_modifiers_verbatim",
3868 description: r##"# `native_link_modifiers_verbatim`
3869
3870The tracking issue for this feature is: [#81490]
3871
3872[#81490]: https://github.com/rust-lang/rust/issues/81490
3873
3874------------------------
3875
3876The `native_link_modifiers_verbatim` feature allows you to use the `verbatim` modifier.
3877
3878`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes (like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the linker.
3879
3880For `ld`-like linkers rustc will use the `-l:filename` syntax (note the colon) when passing the library, so the linker won't add any prefixes or suffixes as well.
3881See [`-l namespec`](https://sourceware.org/binutils/docs/ld/Options.html) in ld documentation for more details.
3882For linkers not supporting any verbatim modifiers (e.g. `link.exe` or `ld64`) the library name will be passed as is.
3883
3884The default for this modifier is `-verbatim`.
3885
3886This RFC changes the behavior of `raw-dylib` linking kind specified by [RFC 2627](https://github.com/rust-lang/rfcs/pull/2627). The `.dll` suffix (or other target-specified suffixes for other targets) is now added automatically.
3887If your DLL doesn't have the `.dll` suffix, it can be specified with `+verbatim`.
3888"##,
3889 },
3890 Lint {
3891 label: "native_link_modifiers_whole_archive",
3892 description: r##"# `native_link_modifiers_whole_archive`
3893
3894The tracking issue for this feature is: [#81490]
3895
3896[#81490]: https://github.com/rust-lang/rust/issues/81490
3897
3898------------------------
3899
3900The `native_link_modifiers_whole_archive` feature allows you to use the `whole-archive` modifier.
3901
3902Only compatible with the `static` linking kind. Using any other kind will result in a compiler error.
3903
3904`+whole-archive` means that the static library is linked as a whole archive without throwing any object files away.
3905
3906This modifier translates to `--whole-archive` for `ld`-like linkers, to `/WHOLEARCHIVE` for `link.exe`, and to `-force_load` for `ld64`.
3907The modifier does nothing for linkers that don't support it.
3908
3909The default for this modifier is `-whole-archive`.
3910"##,
3911 },
3912 Lint {
3913 label: "negative_impls",
3914 description: r##"# `negative_impls`
3915
3916The tracking issue for this feature is [#68318].
3917
3918[#68318]: https://github.com/rust-lang/rust/issues/68318
3919
3920----
3921
3922With the feature gate `negative_impls`, you can write negative impls as well as positive ones:
3923
3924```rust
3925#![feature(negative_impls)]
3926trait DerefMut { }
3927impl<T: ?Sized> !DerefMut for &T { }
3928```
3929
3930Negative impls indicate a semver guarantee that the given trait will not be implemented for the given types. Negative impls play an additional purpose for auto traits, described below.
3931
3932Negative impls have the following characteristics:
3933
3934* They do not have any items.
3935* They must obey the orphan rules as if they were a positive impl.
3936* They cannot "overlap" with any positive impls.
3937
3938## Semver interaction
3939
3940It is a breaking change to remove a negative impl. Negative impls are a commitment not to implement the given trait for the named types.
3941
3942## Orphan and overlap rules
3943
3944Negative impls must obey the same orphan rules as a positive impl. This implies you cannot add a negative impl for types defined in upstream crates and so forth.
3945
3946Similarly, negative impls cannot overlap with positive impls, again using the same "overlap" check that we ordinarily use to determine if two impls overlap. (Note that positive impls typically cannot overlap with one another either, except as permitted by specialization.)
3947
3948## Interaction with auto traits
3949
3950Declaring a negative impl `impl !SomeAutoTrait for SomeType` for an
3951auto-trait serves two purposes:
3952
3953* as with any trait, it declares that `SomeType` will never implement `SomeAutoTrait`;
3954* it disables the automatic `SomeType: SomeAutoTrait` impl that would otherwise have been generated.
3955
3956Note that, at present, there is no way to indicate that a given type
3957does not implement an auto trait *but that it may do so in the
3958future*. For ordinary types, this is done by simply not declaring any
3959impl at all, but that is not an option for auto traits. A workaround
3960is that one could embed a marker type as one of the fields, where the
3961marker type is `!AutoTrait`.
3962
3963## Immediate uses
3964
3965Negative impls are used to declare that `&T: !DerefMut` and `&mut T: !Clone`, as required to fix the soundness of `Pin` described in [#66544](https://github.com/rust-lang/rust/issues/66544).
3966
3967This serves two purposes:
3968
3969* For proving the correctness of unsafe code, we can use that impl as evidence that no `DerefMut` or `Clone` impl exists.
3970* It prevents downstream crates from creating such impls.
3971"##,
3972 },
3973 Lint {
3974 label: "no_coverage",
3975 description: r##"# `no_coverage`
3976
3977The tracking issue for this feature is: [#84605]
3978
3979[#84605]: https://github.com/rust-lang/rust/issues/84605
3980
3981---
3982
3983The `no_coverage` attribute can be used to selectively disable coverage
3984instrumentation in an annotated function. This might be useful to:
3985
3986- Avoid instrumentation overhead in a performance critical function
3987- Avoid generating coverage for a function that is not meant to be executed,
3988 but still target 100% coverage for the rest of the program.
3989
3990## Example
3991
3992```rust
3993#![feature(no_coverage)]
3994
3995// `foo()` will get coverage instrumentation (by default)
3996fn foo() {
3997 // ...
3998}
3999
4000#[no_coverage]
4001fn bar() {
4002 // ...
4003}
4004```
4005"##,
4006 },
4007 Lint {
4008 label: "no_sanitize",
4009 description: r##"# `no_sanitize`
4010
4011The tracking issue for this feature is: [#39699]
4012
4013[#39699]: https://github.com/rust-lang/rust/issues/39699
4014
4015------------------------
4016
4017The `no_sanitize` attribute can be used to selectively disable sanitizer
4018instrumentation in an annotated function. This might be useful to: avoid
4019instrumentation overhead in a performance critical function, or avoid
4020instrumenting code that contains constructs unsupported by given sanitizer.
4021
4022The precise effect of this annotation depends on particular sanitizer in use.
4023For example, with `no_sanitize(thread)`, the thread sanitizer will no longer
4024instrument non-atomic store / load operations, but it will instrument atomic
4025operations to avoid reporting false positives and provide meaning full stack
4026traces.
4027
4028## Examples
4029
4030``` rust
4031#![feature(no_sanitize)]
4032
4033#[no_sanitize(address)]
4034fn foo() {
4035 // ...
4036}
4037```
4038"##,
4039 },
4040 Lint {
4041 label: "plugin",
4042 description: r##"# `plugin`
4043
4044The tracking issue for this feature is: [#29597]
4045
4046[#29597]: https://github.com/rust-lang/rust/issues/29597
4047
4048
4049This feature is part of "compiler plugins." It will often be used with the
4050[`plugin_registrar`] and `rustc_private` features.
4051
4052[`plugin_registrar`]: plugin-registrar.md
4053
4054------------------------
4055
4056`rustc` can load compiler plugins, which are user-provided libraries that
4057extend the compiler's behavior with new lint checks, etc.
4058
4059A plugin is a dynamic library crate with a designated *registrar* function that
4060registers extensions with `rustc`. Other crates can load these extensions using
4061the crate attribute `#![plugin(...)]`. See the
4062`rustc_driver::plugin` documentation for more about the
4063mechanics of defining and loading a plugin.
4064
4065In the vast majority of cases, a plugin should *only* be used through
4066`#![plugin]` and not through an `extern crate` item. Linking a plugin would
4067pull in all of librustc_ast and librustc as dependencies of your crate. This is
4068generally unwanted unless you are building another plugin.
4069
4070The usual practice is to put compiler plugins in their own crate, separate from
4071any `macro_rules!` macros or ordinary Rust code meant to be used by consumers
4072of a library.
4073
4074# Lint plugins
4075
4076Plugins can extend [Rust's lint
4077infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with
4078additional checks for code style, safety, etc. Now let's write a plugin
4079[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs)
4080that warns about any item named `lintme`.
4081
4082```rust,ignore (requires-stage-2)
4083#![feature(plugin_registrar)]
4084#![feature(box_syntax, rustc_private)]
4085
4086extern crate rustc_ast;
4087
4088// Load rustc as a plugin to get macros
4089extern crate rustc_driver;
4090#[macro_use]
4091extern crate rustc_lint;
4092#[macro_use]
4093extern crate rustc_session;
4094
4095use rustc_driver::plugin::Registry;
4096use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
4097use rustc_ast::ast;
4098declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
4099
4100declare_lint_pass!(Pass => [TEST_LINT]);
4101
4102impl EarlyLintPass for Pass {
4103 fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
4104 if it.ident.name.as_str() == "lintme" {
4105 cx.lint(TEST_LINT, |lint| {
4106 lint.build("item is named 'lintme'").set_span(it.span).emit()
4107 });
4108 }
4109 }
4110}
4111
4112#[plugin_registrar]
4113pub fn plugin_registrar(reg: &mut Registry) {
4114 reg.lint_store.register_lints(&[&TEST_LINT]);
4115 reg.lint_store.register_early_pass(|| box Pass);
4116}
4117```
4118
4119Then code like
4120
4121```rust,ignore (requires-plugin)
4122#![feature(plugin)]
4123#![plugin(lint_plugin_test)]
4124
4125fn lintme() { }
4126```
4127
4128will produce a compiler warning:
4129
4130```txt
4131foo.rs:4:1: 4:16 warning: item is named 'lintme', #[warn(test_lint)] on by default
4132foo.rs:4 fn lintme() { }
4133 ^~~~~~~~~~~~~~~
4134```
4135
4136The components of a lint plugin are:
4137
4138* one or more `declare_lint!` invocations, which define static `Lint` structs;
4139
4140* a struct holding any state needed by the lint pass (here, none);
4141
4142* a `LintPass`
4143 implementation defining how to check each syntax element. A single
4144 `LintPass` may call `span_lint` for several different `Lint`s, but should
4145 register them all through the `get_lints` method.
4146
4147Lint passes are syntax traversals, but they run at a late stage of compilation
4148where type information is available. `rustc`'s [built-in
4149lints](https://github.com/rust-lang/rust/blob/master/src/librustc_session/lint/builtin.rs)
4150mostly use the same infrastructure as lint plugins, and provide examples of how
4151to access type information.
4152
4153Lints defined by plugins are controlled by the usual [attributes and compiler
4154flags](../../reference/attributes/diagnostics.md#lint-check-attributes), e.g.
4155`#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the
4156first argument to `declare_lint!`, with appropriate case and punctuation
4157conversion.
4158
4159You can run `rustc -W help foo.rs` to see a list of lints known to `rustc`,
4160including those provided by plugins loaded by `foo.rs`.
4161"##,
4162 },
4163 Lint {
4164 label: "plugin_registrar",
4165 description: r##"# `plugin_registrar`
4166
4167The tracking issue for this feature is: [#29597]
4168
4169[#29597]: https://github.com/rust-lang/rust/issues/29597
4170
4171This feature is part of "compiler plugins." It will often be used with the
4172[`plugin`] and `rustc_private` features as well. For more details, see
4173their docs.
4174
4175[`plugin`]: plugin.md
4176
4177------------------------
4178"##,
4179 },
4180 Lint {
4181 label: "print_internals",
4182 description: r##"# `print_internals`
4183
4184This feature is internal to the Rust compiler and is not intended for general use.
4185
4186------------------------
4187"##,
4188 },
4189 Lint {
4190 label: "profiler_runtime",
4191 description: r##"# `profiler_runtime`
4192
4193The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524).
4194
4195------------------------
4196"##,
4197 },
4198 Lint {
4199 label: "profiler_runtime_lib",
4200 description: r##"# `profiler_runtime_lib`
4201
4202This feature is internal to the Rust compiler and is not intended for general use.
4203
4204------------------------
4205"##,
4206 },
4207 Lint {
4208 label: "repr128",
4209 description: r##"# `repr128`
4210
4211The tracking issue for this feature is: [#56071]
4212
4213[#56071]: https://github.com/rust-lang/rust/issues/56071
4214
4215------------------------
4216
4217The `repr128` feature adds support for `#[repr(u128)]` on `enum`s.
4218
4219```rust
4220#![feature(repr128)]
4221
4222#[repr(u128)]
4223enum Foo {
4224 Bar(u64),
4225}
4226```
4227"##,
4228 },
4229 Lint {
4230 label: "rt",
4231 description: r##"# `rt`
4232
4233This feature is internal to the Rust compiler and is not intended for general use.
4234
4235------------------------
4236"##,
4237 },
4238 Lint {
4239 label: "rustc_attrs",
4240 description: r##"# `rustc_attrs`
4241
4242This feature has no tracking issue, and is therefore internal to
4243the compiler, not being intended for general use.
4244
4245Note: `rustc_attrs` enables many rustc-internal attributes and this page
4246only discuss a few of them.
4247
4248------------------------
4249
4250The `rustc_attrs` feature allows debugging rustc type layouts by using
4251`#[rustc_layout(...)]` to debug layout at compile time (it even works
4252with `cargo check`) as an alternative to `rustc -Z print-type-sizes`
4253that is way more verbose.
4254
4255Options provided by `#[rustc_layout(...)]` are `debug`, `size`, `align`,
4256`abi`. Note that it only works on sized types without generics.
4257
4258## Examples
4259
4260```rust,compile_fail
4261#![feature(rustc_attrs)]
4262
4263#[rustc_layout(abi, size)]
4264pub enum X {
4265 Y(u8, u8, u8),
4266 Z(isize),
4267}
4268```
4269
4270When that is compiled, the compiler will error with something like
4271
4272```text
4273error: abi: Aggregate { sized: true }
4274 --> src/lib.rs:4:1
4275 |
42764 | / pub enum T {
42775 | | Y(u8, u8, u8),
42786 | | Z(isize),
42797 | | }
4280 | |_^
4281
4282error: size: Size { raw: 16 }
4283 --> src/lib.rs:4:1
4284 |
42854 | / pub enum T {
42865 | | Y(u8, u8, u8),
42876 | | Z(isize),
42887 | | }
4289 | |_^
4290
4291error: aborting due to 2 previous errors
4292```
4293"##,
4294 },
4295 Lint {
4296 label: "sort_internals",
4297 description: r##"# `sort_internals`
4298
4299This feature is internal to the Rust compiler and is not intended for general use.
4300
4301------------------------
4302"##,
4303 },
4304 Lint {
4305 label: "str_internals",
4306 description: r##"# `str_internals`
4307
4308This feature is internal to the Rust compiler and is not intended for general use.
4309
4310------------------------
4311"##,
4312 },
4313 Lint {
4314 label: "test",
4315 description: r##"# `test`
4316
4317The tracking issue for this feature is: None.
4318
4319------------------------
4320
4321The internals of the `test` crate are unstable, behind the `test` flag. The
4322most widely used part of the `test` crate are benchmark tests, which can test
4323the performance of your code. Let's make our `src/lib.rs` look like this
4324(comments elided):
4325
4326```rust,no_run
4327#![feature(test)]
4328
4329extern crate test;
4330
4331pub fn add_two(a: i32) -> i32 {
4332 a + 2
4333}
4334
4335#[cfg(test)]
4336mod tests {
4337 use super::*;
4338 use test::Bencher;
4339
4340 #[test]
4341 fn it_works() {
4342 assert_eq!(4, add_two(2));
4343 }
4344
4345 #[bench]
4346 fn bench_add_two(b: &mut Bencher) {
4347 b.iter(|| add_two(2));
4348 }
4349}
4350```
4351
4352Note the `test` feature gate, which enables this unstable feature.
4353
4354We've imported the `test` crate, which contains our benchmarking support.
4355We have a new function as well, with the `bench` attribute. Unlike regular
4356tests, which take no arguments, benchmark tests take a `&mut Bencher`. This
4357`Bencher` provides an `iter` method, which takes a closure. This closure
4358contains the code we'd like to benchmark.
4359
4360We can run benchmark tests with `cargo bench`:
4361
4362```bash
4363$ cargo bench
4364 Compiling adder v0.0.1 (file:///home/steve/tmp/adder)
4365 Running target/release/adder-91b3e234d4ed382a
4366
4367running 2 tests
4368test tests::it_works ... ignored
4369test tests::bench_add_two ... bench: 1 ns/iter (+/- 0)
4370
4371test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured
4372```
4373
4374Our non-benchmark test was ignored. You may have noticed that `cargo bench`
4375takes a bit longer than `cargo test`. This is because Rust runs our benchmark
4376a number of times, and then takes the average. Because we're doing so little
4377work in this example, we have a `1 ns/iter (+/- 0)`, but this would show
4378the variance if there was one.
4379
4380Advice on writing benchmarks:
4381
4382
4383* Move setup code outside the `iter` loop; only put the part you want to measure inside
4384* Make the code do "the same thing" on each iteration; do not accumulate or change state
4385* Make the outer function idempotent too; the benchmark runner is likely to run
4386 it many times
4387* Make the inner `iter` loop short and fast so benchmark runs are fast and the
4388 calibrator can adjust the run-length at fine resolution
4389* Make the code in the `iter` loop do something simple, to assist in pinpointing
4390 performance improvements (or regressions)
4391
4392## Gotcha: optimizations
4393
4394There's another tricky part to writing benchmarks: benchmarks compiled with
4395optimizations activated can be dramatically changed by the optimizer so that
4396the benchmark is no longer benchmarking what one expects. For example, the
4397compiler might recognize that some calculation has no external effects and
4398remove it entirely.
4399
4400```rust,no_run
4401#![feature(test)]
4402
4403extern crate test;
4404use test::Bencher;
4405
4406#[bench]
4407fn bench_xor_1000_ints(b: &mut Bencher) {
4408 b.iter(|| {
4409 (0..1000).fold(0, |old, new| old ^ new);
4410 });
4411}
4412```
4413
4414gives the following results
4415
4416```text
4417running 1 test
4418test bench_xor_1000_ints ... bench: 0 ns/iter (+/- 0)
4419
4420test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
4421```
4422
4423The benchmarking runner offers two ways to avoid this. Either, the closure that
4424the `iter` method receives can return an arbitrary value which forces the
4425optimizer to consider the result used and ensures it cannot remove the
4426computation entirely. This could be done for the example above by adjusting the
4427`b.iter` call to
4428
4429```rust
4430# struct X;
4431# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
4432b.iter(|| {
4433 // Note lack of `;` (could also use an explicit `return`).
4434 (0..1000).fold(0, |old, new| old ^ new)
4435});
4436```
4437
4438Or, the other option is to call the generic `test::black_box` function, which
4439is an opaque "black box" to the optimizer and so forces it to consider any
4440argument as used.
4441
4442```rust
4443#![feature(test)]
4444
4445extern crate test;
4446
4447# fn main() {
4448# struct X;
4449# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
4450b.iter(|| {
4451 let n = test::black_box(1000);
4452
4453 (0..n).fold(0, |a, b| a ^ b)
4454})
4455# }
4456```
4457
4458Neither of these read or modify the value, and are very cheap for small values.
4459Larger values can be passed indirectly to reduce overhead (e.g.
4460`black_box(&huge_struct)`).
4461
4462Performing either of the above changes gives the following benchmarking results
4463
4464```text
4465running 1 test
4466test bench_xor_1000_ints ... bench: 131 ns/iter (+/- 3)
4467
4468test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
4469```
4470
4471However, the optimizer can still modify a testcase in an undesirable manner
4472even when using either of the above.
4473"##,
4474 },
4475 Lint {
4476 label: "thread_local_internals",
4477 description: r##"# `thread_local_internals`
4478
4479This feature is internal to the Rust compiler and is not intended for general use.
4480
4481------------------------
4482"##,
4483 },
4484 Lint {
4485 label: "trace_macros",
4486 description: r##"# `trace_macros`
4487
4488The tracking issue for this feature is [#29598].
4489
4490[#29598]: https://github.com/rust-lang/rust/issues/29598
4491
4492------------------------
4493
4494With `trace_macros` you can trace the expansion of macros in your code.
4495
4496## Examples
4497
4498```rust
4499#![feature(trace_macros)]
4500
4501fn main() {
4502 trace_macros!(true);
4503 println!("Hello, Rust!");
4504 trace_macros!(false);
4505}
4506```
4507
4508The `cargo build` output:
4509
4510```txt
4511note: trace_macro
4512 --> src/main.rs:5:5
4513 |
45145 | println!("Hello, Rust!");
4515 | ^^^^^^^^^^^^^^^^^^^^^^^^^
4516 |
4517 = note: expanding `println! { "Hello, Rust!" }`
4518 = note: to `print ! ( concat ! ( "Hello, Rust!" , "\n" ) )`
4519 = note: expanding `print! { concat ! ( "Hello, Rust!" , "\n" ) }`
4520 = note: to `$crate :: io :: _print ( format_args ! ( concat ! ( "Hello, Rust!" , "\n" ) )
4521 )`
4522
4523 Finished dev [unoptimized + debuginfo] target(s) in 0.60 secs
4524```
4525"##,
4526 },
4527 Lint {
4528 label: "trait_alias",
4529 description: r##"# `trait_alias`
4530
4531The tracking issue for this feature is: [#41517]
4532
4533[#41517]: https://github.com/rust-lang/rust/issues/41517
4534
4535------------------------
4536
4537The `trait_alias` feature adds support for trait aliases. These allow aliases
4538to be created for one or more traits (currently just a single regular trait plus
4539any number of auto-traits), and used wherever traits would normally be used as
4540either bounds or trait objects.
4541
4542```rust
4543#![feature(trait_alias)]
4544
4545trait Foo = std::fmt::Debug + Send;
4546trait Bar = Foo + Sync;
4547
4548// Use trait alias as bound on type parameter.
4549fn foo<T: Foo>(v: &T) {
4550 println!("{:?}", v);
4551}
4552
4553pub fn main() {
4554 foo(&1);
4555
4556 // Use trait alias for trait objects.
4557 let a: &Bar = &123;
4558 println!("{:?}", a);
4559 let b = Box::new(456) as Box<dyn Foo>;
4560 println!("{:?}", b);
4561}
4562```
4563"##,
4564 },
4565 Lint {
4566 label: "transparent_unions",
4567 description: r##"# `transparent_unions`
4568
4569The tracking issue for this feature is [#60405]
4570
4571[#60405]: https://github.com/rust-lang/rust/issues/60405
4572
4573----
4574
4575The `transparent_unions` feature allows you mark `union`s as
4576`#[repr(transparent)]`. A `union` may be `#[repr(transparent)]` in exactly the
4577same conditions in which a `struct` may be `#[repr(transparent)]` (generally,
4578this means the `union` must have exactly one non-zero-sized field). Some
4579concrete illustrations follow.
4580
4581```rust
4582#![feature(transparent_unions)]
4583
4584// This union has the same representation as `f32`.
4585#[repr(transparent)]
4586union SingleFieldUnion {
4587 field: f32,
4588}
4589
4590// This union has the same representation as `usize`.
4591#[repr(transparent)]
4592union MultiFieldUnion {
4593 field: usize,
4594 nothing: (),
4595}
4596```
4597
4598For consistency with transparent `struct`s, `union`s must have exactly one
4599non-zero-sized field. If all fields are zero-sized, the `union` must not be
4600`#[repr(transparent)]`:
4601
4602```rust
4603#![feature(transparent_unions)]
4604
4605// This (non-transparent) union is already valid in stable Rust:
4606pub union GoodUnion {
4607 pub nothing: (),
4608}
4609
4610// Error: transparent union needs exactly one non-zero-sized field, but has 0
4611// #[repr(transparent)]
4612// pub union BadUnion {
4613// pub nothing: (),
4614// }
4615```
4616
4617The one exception is if the `union` is generic over `T` and has a field of type
4618`T`, it may be `#[repr(transparent)]` even if `T` is a zero-sized type:
4619
4620```rust
4621#![feature(transparent_unions)]
4622
4623// This union has the same representation as `T`.
4624#[repr(transparent)]
4625pub union GenericUnion<T: Copy> { // Unions with non-`Copy` fields are unstable.
4626 pub field: T,
4627 pub nothing: (),
4628}
4629
4630// This is okay even though `()` is a zero-sized type.
4631pub const THIS_IS_OKAY: GenericUnion<()> = GenericUnion { field: () };
4632```
4633
4634Like transarent `struct`s, a transparent `union` of type `U` has the same
4635layout, size, and ABI as its single non-ZST field. If it is generic over a type
4636`T`, and all its fields are ZSTs except for exactly one field of type `T`, then
4637it has the same layout and ABI as `T` (even if `T` is a ZST when monomorphized).
4638
4639Like transparent `struct`s, transparent `union`s are FFI-safe if and only if
4640their underlying representation type is also FFI-safe.
4641
4642A `union` may not be eligible for the same nonnull-style optimizations that a
4643`struct` or `enum` (with the same fields) are eligible for. Adding
4644`#[repr(transparent)]` to `union` does not change this. To give a more concrete
4645example, it is unspecified whether `size_of::<T>()` is equal to
4646`size_of::<Option<T>>()`, where `T` is a `union` (regardless of whether or not
4647it is transparent). The Rust compiler is free to perform this optimization if
4648possible, but is not required to, and different compiler versions may differ in
4649their application of these optimizations.
4650"##,
4651 },
4652 Lint {
4653 label: "try_blocks",
4654 description: r##"# `try_blocks`
4655
4656The tracking issue for this feature is: [#31436]
4657
4658[#31436]: https://github.com/rust-lang/rust/issues/31436
4659
4660------------------------
4661
4662The `try_blocks` feature adds support for `try` blocks. A `try`
4663block creates a new scope one can use the `?` operator in.
4664
4665```rust,edition2018
4666#![feature(try_blocks)]
4667
4668use std::num::ParseIntError;
4669
4670let result: Result<i32, ParseIntError> = try {
4671 "1".parse::<i32>()?
4672 + "2".parse::<i32>()?
4673 + "3".parse::<i32>()?
4674};
4675assert_eq!(result, Ok(6));
4676
4677let result: Result<i32, ParseIntError> = try {
4678 "1".parse::<i32>()?
4679 + "foo".parse::<i32>()?
4680 + "3".parse::<i32>()?
4681};
4682assert!(result.is_err());
4683```
4684"##,
4685 },
4686 Lint {
4687 label: "try_trait",
4688 description: r##"# `try_trait`
4689
4690The tracking issue for this feature is: [#42327]
4691
4692[#42327]: https://github.com/rust-lang/rust/issues/42327
4693
4694------------------------
4695
4696This introduces a new trait `Try` for extending the `?` operator to types
4697other than `Result` (a part of [RFC 1859]). The trait provides the canonical
4698way to _view_ a type in terms of a success/failure dichotomy. This will
4699allow `?` to supplant the `try_opt!` macro on `Option` and the `try_ready!`
4700macro on `Poll`, among other things.
4701
4702[RFC 1859]: https://github.com/rust-lang/rfcs/pull/1859
4703
4704Here's an example implementation of the trait:
4705
4706```rust,ignore (cannot-reimpl-Try)
4707/// A distinct type to represent the `None` value of an `Option`.
4708///
4709/// This enables using the `?` operator on `Option`; it's rarely useful alone.
4710#[derive(Debug)]
4711#[unstable(feature = "try_trait", issue = "42327")]
4712pub struct None { _priv: () }
4713
4714#[unstable(feature = "try_trait", issue = "42327")]
4715impl<T> ops::Try for Option<T> {
4716 type Ok = T;
4717 type Error = None;
4718
4719 fn into_result(self) -> Result<T, None> {
4720 self.ok_or(None { _priv: () })
4721 }
4722
4723 fn from_ok(v: T) -> Self {
4724 Some(v)
4725 }
4726
4727 fn from_error(_: None) -> Self {
4728 None
4729 }
4730}
4731```
4732
4733Note the `Error` associated type here is a new marker. The `?` operator
4734allows interconversion between different `Try` implementers only when
4735the error type can be converted `Into` the error type of the enclosing
4736function (or catch block). Having a distinct error type (as opposed to
4737just `()`, or similar) restricts this to where it's semantically meaningful.
4738"##,
4739 },
4740 Lint {
4741 label: "unboxed_closures",
4742 description: r##"# `unboxed_closures`
4743
4744The tracking issue for this feature is [#29625]
4745
4746See Also: [`fn_traits`](../library-features/fn-traits.md)
4747
4748[#29625]: https://github.com/rust-lang/rust/issues/29625
4749
4750----
4751
4752The `unboxed_closures` feature allows you to write functions using the `"rust-call"` ABI,
4753required for implementing the [`Fn*`] family of traits. `"rust-call"` functions must have
4754exactly one (non self) argument, a tuple representing the argument list.
4755
4756[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
4757
4758```rust
4759#![feature(unboxed_closures)]
4760
4761extern "rust-call" fn add_args(args: (u32, u32)) -> u32 {
4762 args.0 + args.1
4763}
4764
4765fn main() {}
4766```
4767"##,
4768 },
4769 Lint {
4770 label: "unsized_locals",
4771 description: r##"# `unsized_locals`
4772
4773The tracking issue for this feature is: [#48055]
4774
4775[#48055]: https://github.com/rust-lang/rust/issues/48055
4776
4777------------------------
4778
4779This implements [RFC1909]. When turned on, you can have unsized arguments and locals:
4780
4781[RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-unsized-rvalues.md
4782
4783```rust
4784#![allow(incomplete_features)]
4785#![feature(unsized_locals, unsized_fn_params)]
4786
4787use std::any::Any;
4788
4789fn main() {
4790 let x: Box<dyn Any> = Box::new(42);
4791 let x: dyn Any = *x;
4792 // ^ unsized local variable
4793 // ^^ unsized temporary
4794 foo(x);
4795}
4796
4797fn foo(_: dyn Any) {}
4798// ^^^^^^ unsized argument
4799```
4800
4801The RFC still forbids the following unsized expressions:
4802
4803```rust,compile_fail
4804#![feature(unsized_locals)]
4805
4806use std::any::Any;
4807
4808struct MyStruct<T: ?Sized> {
4809 content: T,
4810}
4811
4812struct MyTupleStruct<T: ?Sized>(T);
4813
4814fn answer() -> Box<dyn Any> {
4815 Box::new(42)
4816}
4817
4818fn main() {
4819 // You CANNOT have unsized statics.
4820 static X: dyn Any = *answer(); // ERROR
4821 const Y: dyn Any = *answer(); // ERROR
4822
4823 // You CANNOT have struct initialized unsized.
4824 MyStruct { content: *answer() }; // ERROR
4825 MyTupleStruct(*answer()); // ERROR
4826 (42, *answer()); // ERROR
4827
4828 // You CANNOT have unsized return types.
4829 fn my_function() -> dyn Any { *answer() } // ERROR
4830
4831 // You CAN have unsized local variables...
4832 let mut x: dyn Any = *answer(); // OK
4833 // ...but you CANNOT reassign to them.
4834 x = *answer(); // ERROR
4835
4836 // You CANNOT even initialize them separately.
4837 let y: dyn Any; // OK
4838 y = *answer(); // ERROR
4839
4840 // Not mentioned in the RFC, but by-move captured variables are also Sized.
4841 let x: dyn Any = *answer();
4842 (move || { // ERROR
4843 let y = x;
4844 })();
4845
4846 // You CAN create a closure with unsized arguments,
4847 // but you CANNOT call it.
4848 // This is an implementation detail and may be changed in the future.
4849 let f = |x: dyn Any| {};
4850 f(*answer()); // ERROR
4851}
4852```
4853
4854## By-value trait objects
4855
4856With this feature, you can have by-value `self` arguments without `Self: Sized` bounds.
4857
4858```rust
4859#![feature(unsized_fn_params)]
4860
4861trait Foo {
4862 fn foo(self) {}
4863}
4864
4865impl<T: ?Sized> Foo for T {}
4866
4867fn main() {
4868 let slice: Box<[i32]> = Box::new([1, 2, 3]);
4869 <[i32] as Foo>::foo(*slice);
4870}
4871```
4872
4873And `Foo` will also be object-safe.
4874
4875```rust
4876#![feature(unsized_fn_params)]
4877
4878trait Foo {
4879 fn foo(self) {}
4880}
4881
4882impl<T: ?Sized> Foo for T {}
4883
4884fn main () {
4885 let slice: Box<dyn Foo> = Box::new([1, 2, 3]);
4886 // doesn't compile yet
4887 <dyn Foo as Foo>::foo(*slice);
4888}
4889```
4890
4891One of the objectives of this feature is to allow `Box<dyn FnOnce>`.
4892
4893## Variable length arrays
4894
4895The RFC also describes an extension to the array literal syntax: `[e; dyn n]`. In the syntax, `n` isn't necessarily a constant expression. The array is dynamically allocated on the stack and has the type of `[T]`, instead of `[T; n]`.
4896
4897```rust,ignore (not-yet-implemented)
4898#![feature(unsized_locals)]
4899
4900fn mergesort<T: Ord>(a: &mut [T]) {
4901 let mut tmp = [T; dyn a.len()];
4902 // ...
4903}
4904
4905fn main() {
4906 let mut a = [3, 1, 5, 6];
4907 mergesort(&mut a);
4908 assert_eq!(a, [1, 3, 5, 6]);
4909}
4910```
4911
4912VLAs are not implemented yet. The syntax isn't final, either. We may need an alternative syntax for Rust 2015 because, in Rust 2015, expressions like `[e; dyn(1)]` would be ambiguous. One possible alternative proposed in the RFC is `[e; n]`: if `n` captures one or more local variables, then it is considered as `[e; dyn n]`.
4913
4914## Advisory on stack usage
4915
4916It's advised not to casually use the `#![feature(unsized_locals)]` feature. Typical use-cases are:
4917
4918- When you need a by-value trait objects.
4919- When you really need a fast allocation of small temporary arrays.
4920
4921Another pitfall is repetitive allocation and temporaries. Currently the compiler simply extends the stack frame every time it encounters an unsized assignment. So for example, the code
4922
4923```rust
4924#![feature(unsized_locals)]
4925
4926fn main() {
4927 let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]);
4928 let _x = {{{{{{{{{{*x}}}}}}}}}};
4929}
4930```
4931
4932and the code
4933
4934```rust
4935#![feature(unsized_locals)]
4936
4937fn main() {
4938 for _ in 0..10 {
4939 let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]);
4940 let _x = *x;
4941 }
4942}
4943```
4944
4945will unnecessarily extend the stack frame.
4946"##,
4947 },
4948 Lint {
4949 label: "unsized_tuple_coercion",
4950 description: r##"# `unsized_tuple_coercion`
4951
4952The tracking issue for this feature is: [#42877]
4953
4954[#42877]: https://github.com/rust-lang/rust/issues/42877
4955
4956------------------------
4957
4958This is a part of [RFC0401]. According to the RFC, there should be an implementation like this:
4959
4960```rust,ignore (partial-example)
4961impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized<U> {}
4962```
4963
4964This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this:
4965
4966```rust
4967#![feature(unsized_tuple_coercion)]
4968
4969fn main() {
4970 let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]);
4971 let y : &([i32; 3], [i32]) = &x;
4972 assert_eq!(y.1[0], 4);
4973}
4974```
4975
4976[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
4977"##,
4978 },
4979 Lint {
4980 label: "update_panic_count",
4981 description: r##"# `update_panic_count`
4982
4983This feature is internal to the Rust compiler and is not intended for general use.
4984
4985------------------------
4986"##,
4987 },
4988 Lint {
4989 label: "windows_c",
4990 description: r##"# `windows_c`
4991
4992This feature is internal to the Rust compiler and is not intended for general use.
4993
4994------------------------
4995"##,
4996 },
4997 Lint {
4998 label: "windows_handle",
4999 description: r##"# `windows_handle`
5000
5001This feature is internal to the Rust compiler and is not intended for general use.
5002
5003------------------------
5004"##,
5005 },
5006 Lint {
5007 label: "windows_net",
5008 description: r##"# `windows_net`
5009
5010This feature is internal to the Rust compiler and is not intended for general use.
5011
5012------------------------
5013"##,
5014 },
5015 Lint {
5016 label: "windows_stdio",
5017 description: r##"# `windows_stdio`
5018
5019This feature is internal to the Rust compiler and is not intended for general use.
5020
5021------------------------
5022"##,
5023 },
5024];
5025
5026pub const CLIPPY_LINTS: &[Lint] = &[
5027 Lint {
5028 label: "clippy::absurd_extreme_comparisons",
5029 description: r##"Checks for comparisons where one side of the relation is
5030either the minimum or maximum value for its type and warns if it involves a
5031case that is always true or always false. Only integer and boolean types are
5032checked."##,
5033 },
5034 Lint {
5035 label: "clippy::almost_swapped",
5036 description: r##"Checks for `foo = bar; bar = foo` sequences."##,
5037 },
5038 Lint {
5039 label: "clippy::approx_constant",
5040 description: r##"Checks for floating point literals that approximate
5041constants which are defined in
5042[`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants)
5043or
5044[`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants),
5045respectively, suggesting to use the predefined constant."##,
5046 },
5047 Lint {
5048 label: "clippy::as_conversions",
5049 description: r##"Checks for usage of `as` conversions.
5050
5051Note that this lint is specialized in linting *every single* use of `as`
5052regardless of whether good alternatives exist or not.
5053If you want more precise lints for `as`, please consider using these separate lints:
5054`unnecessary_cast`, `cast_lossless/possible_truncation/possible_wrap/precision_loss/sign_loss`,
5055`fn_to_numeric_cast(_with_truncation)`, `char_lit_as_u8`, `ref_to_mut` and `ptr_as_ptr`.
5056There is a good explanation the reason why this lint should work in this way and how it is useful
5057[in this issue](https://github.com/rust-lang/rust-clippy/issues/5122)."##,
5058 },
5059 Lint {
5060 label: "clippy::assertions_on_constants",
5061 description: r##"Checks for `assert!(true)` and `assert!(false)` calls."##,
5062 },
5063 Lint {
5064 label: "clippy::assign_op_pattern",
5065 description: r##"Checks for `a = a op b` or `a = b commutative_op a`
5066patterns."##,
5067 },
5068 Lint {
5069 label: "clippy::assign_ops",
5070 description: r##"Nothing. This lint has been deprecated."##,
5071 },
5072 Lint {
5073 label: "clippy::async_yields_async",
5074 description: r##"Checks for async blocks that yield values of types
5075that can themselves be awaited."##,
5076 },
5077 Lint {
5078 label: "clippy::await_holding_lock",
5079 description: r##"Checks for calls to await while holding a
5080non-async-aware MutexGuard."##,
5081 },
5082 Lint {
5083 label: "clippy::await_holding_refcell_ref",
5084 description: r##"Checks for calls to await while holding a
5085`RefCell` `Ref` or `RefMut`."##,
5086 },
5087 Lint {
5088 label: "clippy::bad_bit_mask",
5089 description: r##"Checks for incompatible bit masks in comparisons.
5090
5091The formula for detecting if an expression of the type `_ <bit_op> m
5092<cmp_op> c` (where `<bit_op>` is one of {`&`, `|`} and `<cmp_op>` is one of
5093{`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following
5094table:
5095
5096|Comparison |Bit Op|Example |is always|Formula |
5097|------------|------|------------|---------|----------------------|
5098|`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` |
5099|`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` |
5100|`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` |
5101|`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` |
5102|`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` |
5103|`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` |"##,
5104 },
5105 Lint {
5106 label: "clippy::bind_instead_of_map",
5107 description: r##"Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))` or
5108`_.or_else(|x| Err(y))`."##,
5109 },
5110 Lint {
5111 label: "clippy::blacklisted_name",
5112 description: r##"Checks for usage of blacklisted names for variables, such
5113as `foo`."##,
5114 },
5115 Lint {
5116 label: "clippy::blanket_clippy_restriction_lints",
5117 description: r##"Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category."##,
5118 },
5119 Lint {
5120 label: "clippy::blocks_in_if_conditions",
5121 description: r##"Checks for `if` conditions that use blocks containing an
5122expression, statements or conditions that use closures with blocks."##,
5123 },
5124 Lint {
5125 label: "clippy::bool_assert_comparison",
5126 description: r##"This lint warns about boolean comparisons in assert-like macros."##,
5127 },
5128 Lint {
5129 label: "clippy::bool_comparison",
5130 description: r##"Checks for expressions of the form `x == true`,
5131`x != true` and order comparisons such as `x < true` (or vice versa) and
5132suggest using the variable directly."##,
5133 },
5134 Lint {
5135 label: "clippy::borrow_interior_mutable_const",
5136 description: r##"Checks if `const` items which is interior mutable (e.g.,
5137contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.) has been borrowed directly."##,
5138 },
5139 Lint {
5140 label: "clippy::borrowed_box",
5141 description: r##"Checks for use of `&Box<T>` anywhere in the code.
5142Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##,
5143 },
5144 Lint {
5145 label: "clippy::box_vec",
5146 description: r##"Checks for use of `Box<Vec<_>>` anywhere in the code.
5147Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##,
5148 },
5149 Lint {
5150 label: "clippy::boxed_local",
5151 description: r##"Checks for usage of `Box<T>` where an unboxed `T` would
5152work fine."##,
5153 },
5154 Lint {
5155 label: "clippy::branches_sharing_code",
5156 description: r##"Checks if the `if` and `else` block contain shared code that can be
5157moved out of the blocks."##,
5158 },
5159 Lint {
5160 label: "clippy::builtin_type_shadow",
5161 description: r##"Warns if a generic shadows a built-in type."##,
5162 },
5163 Lint {
5164 label: "clippy::bytes_nth",
5165 description: r##"Checks for the use of `.bytes().nth()`."##,
5166 },
5167 Lint {
5168 label: "clippy::cargo_common_metadata",
5169 description: r##"Checks to see if all common metadata is defined in
5170`Cargo.toml`. See: https://rust-lang-nursery.github.io/api-guidelines/documentation.html#cargotoml-includes-all-common-metadata-c-metadata"##,
5171 },
5172 Lint {
5173 label: "clippy::case_sensitive_file_extension_comparisons",
5174 description: r##"Checks for calls to `ends_with` with possible file extensions
5175and suggests to use a case-insensitive approach instead."##,
5176 },
5177 Lint {
5178 label: "clippy::cast_lossless",
5179 description: r##"Checks for casts between numerical types that may
5180be replaced by safe conversion functions."##,
5181 },
5182 Lint {
5183 label: "clippy::cast_possible_truncation",
5184 description: r##"Checks for casts between numerical types that may
5185truncate large values. This is expected behavior, so the cast is `Allow` by
5186default."##,
5187 },
5188 Lint {
5189 label: "clippy::cast_possible_wrap",
5190 description: r##"Checks for casts from an unsigned type to a signed type of
5191the same size. Performing such a cast is a 'no-op' for the compiler,
5192i.e., nothing is changed at the bit level, and the binary representation of
5193the value is reinterpreted. This can cause wrapping if the value is too big
5194for the target signed type. However, the cast works as defined, so this lint
5195is `Allow` by default."##,
5196 },
5197 Lint {
5198 label: "clippy::cast_precision_loss",
5199 description: r##"Checks for casts from any numerical to a float type where
5200the receiving type cannot store all values from the original type without
5201rounding errors. This possible rounding is to be expected, so this lint is
5202`Allow` by default.
5203
5204Basically, this warns on casting any integer with 32 or more bits to `f32`
5205or any 64-bit integer to `f64`."##,
5206 },
5207 Lint {
5208 label: "clippy::cast_ptr_alignment",
5209 description: r##"Checks for casts, using `as` or `pointer::cast`,
5210from a less-strictly-aligned pointer to a more-strictly-aligned pointer"##,
5211 },
5212 Lint {
5213 label: "clippy::cast_ref_to_mut",
5214 description: r##"Checks for casts of `&T` to `&mut T` anywhere in the code."##,
5215 },
5216 Lint {
5217 label: "clippy::cast_sign_loss",
5218 description: r##"Checks for casts from a signed to an unsigned numerical
5219type. In this case, negative values wrap around to large positive values,
5220which can be quite surprising in practice. However, as the cast works as
5221defined, this lint is `Allow` by default."##,
5222 },
5223 Lint {
5224 label: "clippy::char_lit_as_u8",
5225 description: r##"Checks for expressions where a character literal is cast
5226to `u8` and suggests using a byte literal instead."##,
5227 },
5228 Lint {
5229 label: "clippy::chars_last_cmp",
5230 description: r##"Checks for usage of `_.chars().last()` or
5231`_.chars().next_back()` on a `str` to check if it ends with a given char."##,
5232 },
5233 Lint {
5234 label: "clippy::chars_next_cmp",
5235 description: r##"Checks for usage of `.chars().next()` on a `str` to check
5236if it starts with a given char."##,
5237 },
5238 Lint {
5239 label: "clippy::checked_conversions",
5240 description: r##"Checks for explicit bounds checking when casting."##,
5241 },
5242 Lint {
5243 label: "clippy::clone_double_ref",
5244 description: r##"Checks for usage of `.clone()` on an `&&T`."##,
5245 },
5246 Lint {
5247 label: "clippy::clone_on_copy",
5248 description: r##"Checks for usage of `.clone()` on a `Copy` type."##,
5249 },
5250 Lint {
5251 label: "clippy::clone_on_ref_ptr",
5252 description: r##"Checks for usage of `.clone()` on a ref-counted pointer,
5253(`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified
5254function syntax instead (e.g., `Rc::clone(foo)`)."##,
5255 },
5256 Lint {
5257 label: "clippy::cloned_instead_of_copied",
5258 description: r##"Checks for usages of `cloned()` on an `Iterator` or `Option` where
5259`copied()` could be used instead."##,
5260 },
5261 Lint { label: "clippy::cmp_nan", description: r##"Checks for comparisons to NaN."## },
5262 Lint {
5263 label: "clippy::cmp_null",
5264 description: r##"This lint checks for equality comparisons with `ptr::null`"##,
5265 },
5266 Lint {
5267 label: "clippy::cmp_owned",
5268 description: r##"Checks for conversions to owned values just for the sake
5269of a comparison."##,
5270 },
5271 Lint {
5272 label: "clippy::cognitive_complexity",
5273 description: r##"Checks for methods with high cognitive complexity."##,
5274 },
5275 Lint {
5276 label: "clippy::collapsible_else_if",
5277 description: r##"Checks for collapsible `else { if ... }` expressions
5278that can be collapsed to `else if ...`."##,
5279 },
5280 Lint {
5281 label: "clippy::collapsible_if",
5282 description: r##"Checks for nested `if` statements which can be collapsed
5283by `&&`-combining their conditions."##,
5284 },
5285 Lint {
5286 label: "clippy::collapsible_match",
5287 description: r##"Finds nested `match` or `if let` expressions where the patterns may be collapsed together
5288without adding any branches.
5289
5290Note that this lint is not intended to find _all_ cases where nested match patterns can be merged, but only
5291cases where merging would most likely make the code more readable."##,
5292 },
5293 Lint {
5294 label: "clippy::comparison_chain",
5295 description: r##"Checks comparison chains written with `if` that can be
5296rewritten with `match` and `cmp`."##,
5297 },
5298 Lint {
5299 label: "clippy::comparison_to_empty",
5300 description: r##"Checks for comparing to an empty slice such as `` or `[]`,
5301and suggests using `.is_empty()` where applicable."##,
5302 },
5303 Lint {
5304 label: "clippy::copy_iterator",
5305 description: r##"Checks for types that implement `Copy` as well as
5306`Iterator`."##,
5307 },
5308 Lint {
5309 label: "clippy::create_dir",
5310 description: r##"Checks usage of `std::fs::create_dir` and suggest using `std::fs::create_dir_all` instead."##,
5311 },
5312 Lint {
5313 label: "clippy::crosspointer_transmute",
5314 description: r##"Checks for transmutes between a type `T` and `*T`."##,
5315 },
5316 Lint { label: "clippy::dbg_macro", description: r##"Checks for usage of dbg!() macro."## },
5317 Lint {
5318 label: "clippy::debug_assert_with_mut_call",
5319 description: r##"Checks for function/method calls with a mutable
5320parameter in `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!` macros."##,
5321 },
5322 Lint {
5323 label: "clippy::decimal_literal_representation",
5324 description: r##"Warns if there is a better representation for a numeric literal."##,
5325 },
5326 Lint {
5327 label: "clippy::declare_interior_mutable_const",
5328 description: r##"Checks for declaration of `const` items which is interior
5329mutable (e.g., contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.)."##,
5330 },
5331 Lint {
5332 label: "clippy::default_numeric_fallback",
5333 description: r##"Checks for usage of unconstrained numeric literals which may cause default numeric fallback in type
5334inference.
5335
5336Default numeric fallback means that if numeric types have not yet been bound to concrete
5337types at the end of type inference, then integer type is bound to `i32`, and similarly
5338floating type is bound to `f64`.
5339
5340See [RFC0212](https://github.com/rust-lang/rfcs/blob/master/text/0212-restore-int-fallback.md) for more information about the fallback."##,
5341 },
5342 Lint {
5343 label: "clippy::default_trait_access",
5344 description: r##"Checks for literal calls to `Default::default()`."##,
5345 },
5346 Lint {
5347 label: "clippy::deprecated_cfg_attr",
5348 description: r##"Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it
5349with `#[rustfmt::skip]`."##,
5350 },
5351 Lint {
5352 label: "clippy::deprecated_semver",
5353 description: r##"Checks for `#[deprecated]` annotations with a `since`
5354field that is not a valid semantic version."##,
5355 },
5356 Lint {
5357 label: "clippy::deref_addrof",
5358 description: r##"Checks for usage of `*&` and `*&mut` in expressions."##,
5359 },
5360 Lint {
5361 label: "clippy::derive_hash_xor_eq",
5362 description: r##"Checks for deriving `Hash` but implementing `PartialEq`
5363explicitly or vice versa."##,
5364 },
5365 Lint {
5366 label: "clippy::derive_ord_xor_partial_ord",
5367 description: r##"Checks for deriving `Ord` but implementing `PartialOrd`
5368explicitly or vice versa."##,
5369 },
5370 Lint {
5371 label: "clippy::disallowed_method",
5372 description: r##"Denies the configured methods and functions in clippy.toml"##,
5373 },
5374 Lint {
5375 label: "clippy::diverging_sub_expression",
5376 description: r##"Checks for diverging calls that are not match arms or
5377statements."##,
5378 },
5379 Lint {
5380 label: "clippy::doc_markdown",
5381 description: r##"Checks for the presence of `_`, `::` or camel-case words
5382outside ticks in documentation."##,
5383 },
5384 Lint {
5385 label: "clippy::double_comparisons",
5386 description: r##"Checks for double comparisons that could be simplified to a single expression."##,
5387 },
5388 Lint {
5389 label: "clippy::double_must_use",
5390 description: r##"Checks for a [`#[must_use]`] attribute without
5391further information on functions and methods that return a type already
5392marked as `#[must_use]`.
5393
5394[`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute"##,
5395 },
5396 Lint {
5397 label: "clippy::double_neg",
5398 description: r##"Detects expressions of the form `--x`."##,
5399 },
5400 Lint {
5401 label: "clippy::double_parens",
5402 description: r##"Checks for unnecessary double parentheses."##,
5403 },
5404 Lint {
5405 label: "clippy::drop_copy",
5406 description: r##"Checks for calls to `std::mem::drop` with a value
5407that derives the Copy trait"##,
5408 },
5409 Lint {
5410 label: "clippy::drop_ref",
5411 description: r##"Checks for calls to `std::mem::drop` with a reference
5412instead of an owned value."##,
5413 },
5414 Lint {
5415 label: "clippy::duplicate_underscore_argument",
5416 description: r##"Checks for function arguments having the similar names
5417differing by an underscore."##,
5418 },
5419 Lint {
5420 label: "clippy::duration_subsec",
5421 description: r##"Checks for calculation of subsecond microseconds or milliseconds
5422from other `Duration` methods."##,
5423 },
5424 Lint {
5425 label: "clippy::else_if_without_else",
5426 description: r##"Checks for usage of if expressions with an `else if` branch,
5427but without a final `else` branch."##,
5428 },
5429 Lint {
5430 label: "clippy::empty_enum",
5431 description: r##"Checks for `enum`s with no variants.
5432
5433As of this writing, the `never_type` is still a
5434nightly-only experimental API. Therefore, this lint is only triggered
5435if the `never_type` is enabled."##,
5436 },
5437 Lint {
5438 label: "clippy::empty_line_after_outer_attr",
5439 description: r##"Checks for empty lines after outer attributes"##,
5440 },
5441 Lint { label: "clippy::empty_loop", description: r##"Checks for empty `loop` expressions."## },
5442 Lint {
5443 label: "clippy::enum_clike_unportable_variant",
5444 description: r##"Checks for C-like enumerations that are
5445`repr(isize/usize)` and have values that don't fit into an `i32`."##,
5446 },
5447 Lint { label: "clippy::enum_glob_use", description: r##"Checks for `use Enum::*`."## },
5448 Lint {
5449 label: "clippy::enum_variant_names",
5450 description: r##"Detects enumeration variants that are prefixed or suffixed
5451by the same characters."##,
5452 },
5453 Lint {
5454 label: "clippy::eq_op",
5455 description: r##"Checks for equal operands to comparison, logical and
5456bitwise, difference and division binary operators (`==`, `>`, etc., `&&`,
5457`||`, `&`, `|`, `^`, `-` and `/`)."##,
5458 },
5459 Lint {
5460 label: "clippy::erasing_op",
5461 description: r##"Checks for erasing operations, e.g., `x * 0`."##,
5462 },
5463 Lint {
5464 label: "clippy::eval_order_dependence",
5465 description: r##"Checks for a read and a write to the same variable where
5466whether the read occurs before or after the write depends on the evaluation
5467order of sub-expressions."##,
5468 },
5469 Lint {
5470 label: "clippy::excessive_precision",
5471 description: r##"Checks for float literals with a precision greater
5472than that supported by the underlying type."##,
5473 },
5474 Lint {
5475 label: "clippy::exhaustive_enums",
5476 description: r##"Warns on any exported `enum`s that are not tagged `#[non_exhaustive]`"##,
5477 },
5478 Lint {
5479 label: "clippy::exhaustive_structs",
5480 description: r##"Warns on any exported `structs`s that are not tagged `#[non_exhaustive]`"##,
5481 },
5482 Lint {
5483 label: "clippy::exit",
5484 description: r##"`exit()` terminates the program and doesn't provide a
5485stack trace."##,
5486 },
5487 Lint {
5488 label: "clippy::expect_fun_call",
5489 description: r##"Checks for calls to `.expect(&format!(...))`, `.expect(foo(..))`,
5490etc., and suggests to use `unwrap_or_else` instead"##,
5491 },
5492 Lint {
5493 label: "clippy::expect_used",
5494 description: r##"Checks for `.expect()` calls on `Option`s and `Result`s."##,
5495 },
5496 Lint {
5497 label: "clippy::expl_impl_clone_on_copy",
5498 description: r##"Checks for explicit `Clone` implementations for `Copy`
5499types."##,
5500 },
5501 Lint {
5502 label: "clippy::explicit_counter_loop",
5503 description: r##"Checks `for` loops over slices with an explicit counter
5504and suggests the use of `.enumerate()`."##,
5505 },
5506 Lint {
5507 label: "clippy::explicit_deref_methods",
5508 description: r##"Checks for explicit `deref()` or `deref_mut()` method calls."##,
5509 },
5510 Lint {
5511 label: "clippy::explicit_into_iter_loop",
5512 description: r##"Checks for loops on `y.into_iter()` where `y` will do, and
5513suggests the latter."##,
5514 },
5515 Lint {
5516 label: "clippy::explicit_iter_loop",
5517 description: r##"Checks for loops on `x.iter()` where `&x` will do, and
5518suggests the latter."##,
5519 },
5520 Lint {
5521 label: "clippy::explicit_write",
5522 description: r##"Checks for usage of `write!()` / `writeln()!` which can be
5523replaced with `(e)print!()` / `(e)println!()`"##,
5524 },
5525 Lint {
5526 label: "clippy::extend_from_slice",
5527 description: r##"Nothing. This lint has been deprecated."##,
5528 },
5529 Lint {
5530 label: "clippy::extra_unused_lifetimes",
5531 description: r##"Checks for lifetimes in generics that are never used
5532anywhere else."##,
5533 },
5534 Lint {
5535 label: "clippy::fallible_impl_from",
5536 description: r##"Checks for impls of `From<..>` that contain `panic!()` or `unwrap()`"##,
5537 },
5538 Lint {
5539 label: "clippy::field_reassign_with_default",
5540 description: r##"Checks for immediate reassignment of fields initialized
5541with Default::default()."##,
5542 },
5543 Lint {
5544 label: "clippy::filetype_is_file",
5545 description: r##"Checks for `FileType::is_file()`."##,
5546 },
5547 Lint {
5548 label: "clippy::filter_map",
5549 description: r##"Nothing. This lint has been deprecated."##,
5550 },
5551 Lint {
5552 label: "clippy::filter_map_identity",
5553 description: r##"Checks for usage of `filter_map(|x| x)`."##,
5554 },
5555 Lint {
5556 label: "clippy::filter_map_next",
5557 description: r##"Checks for usage of `_.filter_map(_).next()`."##,
5558 },
5559 Lint {
5560 label: "clippy::filter_next",
5561 description: r##"Checks for usage of `_.filter(_).next()`."##,
5562 },
5563 Lint { label: "clippy::find_map", description: r##"Nothing. This lint has been deprecated."## },
5564 Lint {
5565 label: "clippy::flat_map_identity",
5566 description: r##"Checks for usage of `flat_map(|x| x)`."##,
5567 },
5568 Lint {
5569 label: "clippy::flat_map_option",
5570 description: r##"Checks for usages of `Iterator::flat_map()` where `filter_map()` could be
5571used instead."##,
5572 },
5573 Lint { label: "clippy::float_arithmetic", description: r##"Checks for float arithmetic."## },
5574 Lint {
5575 label: "clippy::float_cmp",
5576 description: r##"Checks for (in-)equality comparisons on floating-point
5577values (apart from zero), except in functions called `*eq*` (which probably
5578implement equality for a type involving floats)."##,
5579 },
5580 Lint {
5581 label: "clippy::float_cmp_const",
5582 description: r##"Checks for (in-)equality comparisons on floating-point
5583value and constant, except in functions called `*eq*` (which probably
5584implement equality for a type involving floats)."##,
5585 },
5586 Lint {
5587 label: "clippy::float_equality_without_abs",
5588 description: r##"Checks for statements of the form `(a - b) < f32::EPSILON` or
5589`(a - b) < f64::EPSILON`. Notes the missing `.abs()`."##,
5590 },
5591 Lint {
5592 label: "clippy::fn_address_comparisons",
5593 description: r##"Checks for comparisons with an address of a function item."##,
5594 },
5595 Lint {
5596 label: "clippy::fn_params_excessive_bools",
5597 description: r##"Checks for excessive use of
5598bools in function definitions."##,
5599 },
5600 Lint {
5601 label: "clippy::fn_to_numeric_cast",
5602 description: r##"Checks for casts of function pointers to something other than usize"##,
5603 },
5604 Lint {
5605 label: "clippy::fn_to_numeric_cast_with_truncation",
5606 description: r##"Checks for casts of a function pointer to a numeric type not wide enough to
5607store address."##,
5608 },
5609 Lint {
5610 label: "clippy::for_kv_map",
5611 description: r##"Checks for iterating a map (`HashMap` or `BTreeMap`) and
5612ignoring either the keys or values."##,
5613 },
5614 Lint {
5615 label: "clippy::for_loops_over_fallibles",
5616 description: r##"Checks for `for` loops over `Option` or `Result` values."##,
5617 },
5618 Lint {
5619 label: "clippy::forget_copy",
5620 description: r##"Checks for calls to `std::mem::forget` with a value that
5621derives the Copy trait"##,
5622 },
5623 Lint {
5624 label: "clippy::forget_ref",
5625 description: r##"Checks for calls to `std::mem::forget` with a reference
5626instead of an owned value."##,
5627 },
5628 Lint {
5629 label: "clippy::from_iter_instead_of_collect",
5630 description: r##"Checks for `from_iter()` function calls on types that implement the `FromIterator`
5631trait."##,
5632 },
5633 Lint {
5634 label: "clippy::from_over_into",
5635 description: r##"Searches for implementations of the `Into<..>` trait and suggests to implement `From<..>` instead."##,
5636 },
5637 Lint {
5638 label: "clippy::from_str_radix_10",
5639 description: r##"Checks for function invocations of the form `primitive::from_str_radix(s, 10)`"##,
5640 },
5641 Lint {
5642 label: "clippy::future_not_send",
5643 description: r##"This lint requires Future implementations returned from
5644functions and methods to implement the `Send` marker trait. It is mostly
5645used by library authors (public and internal) that target an audience where
5646multithreaded executors are likely to be used for running these Futures."##,
5647 },
5648 Lint {
5649 label: "clippy::get_last_with_len",
5650 description: r##"Checks for using `x.get(x.len() - 1)` instead of
5651`x.last()`."##,
5652 },
5653 Lint {
5654 label: "clippy::get_unwrap",
5655 description: r##"Checks for use of `.get().unwrap()` (or
5656`.get_mut().unwrap`) on a standard library type which implements `Index`"##,
5657 },
5658 Lint {
5659 label: "clippy::identity_op",
5660 description: r##"Checks for identity operations, e.g., `x + 0`."##,
5661 },
5662 Lint {
5663 label: "clippy::if_let_mutex",
5664 description: r##"Checks for `Mutex::lock` calls in `if let` expression
5665with lock calls in any of the else blocks."##,
5666 },
5667 Lint {
5668 label: "clippy::if_let_redundant_pattern_matching",
5669 description: r##"Nothing. This lint has been deprecated."##,
5670 },
5671 Lint {
5672 label: "clippy::if_let_some_result",
5673 description: r##"* Checks for unnecessary `ok()` in if let."##,
5674 },
5675 Lint {
5676 label: "clippy::if_not_else",
5677 description: r##"Checks for usage of `!` or `!=` in an if condition with an
5678else branch."##,
5679 },
5680 Lint {
5681 label: "clippy::if_same_then_else",
5682 description: r##"Checks for `if/else` with the same body as the *then* part
5683and the *else* part."##,
5684 },
5685 Lint {
5686 label: "clippy::if_then_some_else_none",
5687 description: r##"Checks for if-else that could be written to `bool::then`."##,
5688 },
5689 Lint {
5690 label: "clippy::ifs_same_cond",
5691 description: r##"Checks for consecutive `if`s with the same condition."##,
5692 },
5693 Lint {
5694 label: "clippy::implicit_clone",
5695 description: r##"Checks for the usage of `_.to_owned()`, `vec.to_vec()`, or similar when calling `_.clone()` would be clearer."##,
5696 },
5697 Lint {
5698 label: "clippy::implicit_hasher",
5699 description: r##"Checks for public `impl` or `fn` missing generalization
5700over different hashers and implicitly defaulting to the default hashing
5701algorithm (`SipHash`)."##,
5702 },
5703 Lint {
5704 label: "clippy::implicit_return",
5705 description: r##"Checks for missing return statements at the end of a block."##,
5706 },
5707 Lint {
5708 label: "clippy::implicit_saturating_sub",
5709 description: r##"Checks for implicit saturating subtraction."##,
5710 },
5711 Lint {
5712 label: "clippy::imprecise_flops",
5713 description: r##"Looks for floating-point expressions that
5714can be expressed using built-in methods to improve accuracy
5715at the cost of performance."##,
5716 },
5717 Lint {
5718 label: "clippy::inconsistent_digit_grouping",
5719 description: r##"Warns if an integral or floating-point constant is
5720grouped inconsistently with underscores."##,
5721 },
5722 Lint {
5723 label: "clippy::inconsistent_struct_constructor",
5724 description: r##"Checks for struct constructors where all fields are shorthand and
5725the order of the field init shorthand in the constructor is inconsistent
5726with the order in the struct definition."##,
5727 },
5728 Lint {
5729 label: "clippy::indexing_slicing",
5730 description: r##"Checks for usage of indexing or slicing. Arrays are special cases, this lint
5731does report on arrays if we can tell that slicing operations are in bounds and does not
5732lint on constant `usize` indexing on arrays because that is handled by rustc's `const_err` lint."##,
5733 },
5734 Lint {
5735 label: "clippy::ineffective_bit_mask",
5736 description: r##"Checks for bit masks in comparisons which can be removed
5737without changing the outcome. The basic structure can be seen in the
5738following table:
5739
5740|Comparison| Bit Op |Example |equals |
5741|----------|---------|-----------|-------|
5742|`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`|
5743|`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|"##,
5744 },
5745 Lint {
5746 label: "clippy::inefficient_to_string",
5747 description: r##"Checks for usage of `.to_string()` on an `&&T` where
5748`T` implements `ToString` directly (like `&&str` or `&&String`)."##,
5749 },
5750 Lint {
5751 label: "clippy::infallible_destructuring_match",
5752 description: r##"Checks for matches being used to destructure a single-variant enum
5753or tuple struct where a `let` will suffice."##,
5754 },
5755 Lint {
5756 label: "clippy::infinite_iter",
5757 description: r##"Checks for iteration that is guaranteed to be infinite."##,
5758 },
5759 Lint {
5760 label: "clippy::inherent_to_string",
5761 description: r##"Checks for the definition of inherent methods with a signature of `to_string(&self) -> String`."##,
5762 },
5763 Lint {
5764 label: "clippy::inherent_to_string_shadow_display",
5765 description: r##"Checks for the definition of inherent methods with a signature of `to_string(&self) -> String` and if the type implementing this method also implements the `Display` trait."##,
5766 },
5767 Lint {
5768 label: "clippy::inline_always",
5769 description: r##"Checks for items annotated with `#[inline(always)]`,
5770unless the annotated function is empty or simply panics."##,
5771 },
5772 Lint {
5773 label: "clippy::inline_asm_x86_att_syntax",
5774 description: r##"Checks for usage of AT&T x86 assembly syntax."##,
5775 },
5776 Lint {
5777 label: "clippy::inline_asm_x86_intel_syntax",
5778 description: r##"Checks for usage of Intel x86 assembly syntax."##,
5779 },
5780 Lint {
5781 label: "clippy::inline_fn_without_body",
5782 description: r##"Checks for `#[inline]` on trait methods without bodies"##,
5783 },
5784 Lint {
5785 label: "clippy::inspect_for_each",
5786 description: r##"Checks for usage of `inspect().for_each()`."##,
5787 },
5788 Lint {
5789 label: "clippy::int_plus_one",
5790 description: r##"Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block"##,
5791 },
5792 Lint {
5793 label: "clippy::integer_arithmetic",
5794 description: r##"Checks for integer arithmetic operations which could overflow or panic.
5795
5796Specifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable
5797of overflowing according to the [Rust
5798Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),
5799or which can panic (`/`, `%`). No bounds analysis or sophisticated reasoning is
5800attempted."##,
5801 },
5802 Lint { label: "clippy::integer_division", description: r##"Checks for division of integers"## },
5803 Lint {
5804 label: "clippy::into_iter_on_ref",
5805 description: r##"Checks for `into_iter` calls on references which should be replaced by `iter`
5806or `iter_mut`."##,
5807 },
5808 Lint {
5809 label: "clippy::invalid_atomic_ordering",
5810 description: r##"Checks for usage of invalid atomic
5811ordering in atomic loads/stores/exchanges/updates and
5812memory fences."##,
5813 },
5814 Lint {
5815 label: "clippy::invalid_null_ptr_usage",
5816 description: r##"This lint checks for invalid usages of `ptr::null`."##,
5817 },
5818 Lint {
5819 label: "clippy::invalid_regex",
5820 description: r##"Checks [regex](https://crates.io/crates/regex) creation
5821(with `Regex::new`, `RegexBuilder::new`, or `RegexSet::new`) for correct
5822regex syntax."##,
5823 },
5824 Lint {
5825 label: "clippy::invalid_upcast_comparisons",
5826 description: r##"Checks for comparisons where the relation is always either
5827true or false, but where one side has been upcast so that the comparison is
5828necessary. Only integer types are checked."##,
5829 },
5830 Lint {
5831 label: "clippy::invisible_characters",
5832 description: r##"Checks for invisible Unicode characters in the code."##,
5833 },
5834 Lint {
5835 label: "clippy::items_after_statements",
5836 description: r##"Checks for items declared after some statement in a block."##,
5837 },
5838 Lint {
5839 label: "clippy::iter_cloned_collect",
5840 description: r##"Checks for the use of `.cloned().collect()` on slice to
5841create a `Vec`."##,
5842 },
5843 Lint {
5844 label: "clippy::iter_count",
5845 description: r##"Checks for the use of `.iter().count()`."##,
5846 },
5847 Lint { label: "clippy::iter_next_loop", description: r##"Checks for loops on `x.next()`."## },
5848 Lint {
5849 label: "clippy::iter_next_slice",
5850 description: r##"Checks for usage of `iter().next()` on a Slice or an Array"##,
5851 },
5852 Lint {
5853 label: "clippy::iter_nth",
5854 description: r##"Checks for use of `.iter().nth()` (and the related
5855`.iter_mut().nth()`) on standard library types with O(1) element access."##,
5856 },
5857 Lint {
5858 label: "clippy::iter_nth_zero",
5859 description: r##"Checks for the use of `iter.nth(0)`."##,
5860 },
5861 Lint {
5862 label: "clippy::iter_skip_next",
5863 description: r##"Checks for use of `.skip(x).next()` on iterators."##,
5864 },
5865 Lint {
5866 label: "clippy::iterator_step_by_zero",
5867 description: r##"Checks for calling `.step_by(0)` on iterators which panics."##,
5868 },
5869 Lint {
5870 label: "clippy::just_underscores_and_digits",
5871 description: r##"Checks if you have variables whose name consists of just
5872underscores and digits."##,
5873 },
5874 Lint {
5875 label: "clippy::large_const_arrays",
5876 description: r##"Checks for large `const` arrays that should
5877be defined as `static` instead."##,
5878 },
5879 Lint {
5880 label: "clippy::large_digit_groups",
5881 description: r##"Warns if the digits of an integral or floating-point
5882constant are grouped into groups that
5883are too large."##,
5884 },
5885 Lint {
5886 label: "clippy::large_enum_variant",
5887 description: r##"Checks for large size differences between variants on
5888`enum`s."##,
5889 },
5890 Lint {
5891 label: "clippy::large_stack_arrays",
5892 description: r##"Checks for local arrays that may be too large."##,
5893 },
5894 Lint {
5895 label: "clippy::large_types_passed_by_value",
5896 description: r##"Checks for functions taking arguments by value, where
5897the argument type is `Copy` and large enough to be worth considering
5898passing by reference. Does not trigger if the function is being exported,
5899because that might induce API breakage, if the parameter is declared as mutable,
5900or if the argument is a `self`."##,
5901 },
5902 Lint {
5903 label: "clippy::len_without_is_empty",
5904 description: r##"Checks for items that implement `.len()` but not
5905`.is_empty()`."##,
5906 },
5907 Lint {
5908 label: "clippy::len_zero",
5909 description: r##"Checks for getting the length of something via `.len()`
5910just to compare to zero, and suggests using `.is_empty()` where applicable."##,
5911 },
5912 Lint {
5913 label: "clippy::let_and_return",
5914 description: r##"Checks for `let`-bindings, which are subsequently
5915returned."##,
5916 },
5917 Lint {
5918 label: "clippy::let_underscore_drop",
5919 description: r##"Checks for `let _ = <expr>`
5920where expr has a type that implements `Drop`"##,
5921 },
5922 Lint {
5923 label: "clippy::let_underscore_lock",
5924 description: r##"Checks for `let _ = sync_lock`"##,
5925 },
5926 Lint {
5927 label: "clippy::let_underscore_must_use",
5928 description: r##"Checks for `let _ = <expr>`
5929where expr is #[must_use]"##,
5930 },
5931 Lint { label: "clippy::let_unit_value", description: r##"Checks for binding a unit value."## },
5932 Lint {
5933 label: "clippy::linkedlist",
5934 description: r##"Checks for usage of any `LinkedList`, suggesting to use a
5935`Vec` or a `VecDeque` (formerly called `RingBuf`)."##,
5936 },
5937 Lint {
5938 label: "clippy::logic_bug",
5939 description: r##"Checks for boolean expressions that contain terminals that
5940can be eliminated."##,
5941 },
5942 Lint {
5943 label: "clippy::lossy_float_literal",
5944 description: r##"Checks for whole number float literals that
5945cannot be represented as the underlying type without loss."##,
5946 },
5947 Lint {
5948 label: "clippy::macro_use_imports",
5949 description: r##"Checks for `#[macro_use] use...`."##,
5950 },
5951 Lint {
5952 label: "clippy::main_recursion",
5953 description: r##"Checks for recursion using the entrypoint."##,
5954 },
5955 Lint {
5956 label: "clippy::manual_async_fn",
5957 description: r##"It checks for manual implementations of `async` functions."##,
5958 },
5959 Lint {
5960 label: "clippy::manual_filter_map",
5961 description: r##"Checks for usage of `_.filter(_).map(_)` that can be written more simply
5962as `filter_map(_)`."##,
5963 },
5964 Lint {
5965 label: "clippy::manual_find_map",
5966 description: r##"Checks for usage of `_.find(_).map(_)` that can be written more simply
5967as `find_map(_)`."##,
5968 },
5969 Lint {
5970 label: "clippy::manual_flatten",
5971 description: r##"Check for unnecessary `if let` usage in a for loop
5972where only the `Some` or `Ok` variant of the iterator element is used."##,
5973 },
5974 Lint {
5975 label: "clippy::manual_map",
5976 description: r##"Checks for usages of `match` which could be implemented using `map`"##,
5977 },
5978 Lint {
5979 label: "clippy::manual_memcpy",
5980 description: r##"Checks for for-loops that manually copy items between
5981slices that could be optimized by having a memcpy."##,
5982 },
5983 Lint {
5984 label: "clippy::manual_non_exhaustive",
5985 description: r##"Checks for manual implementations of the non-exhaustive pattern."##,
5986 },
5987 Lint {
5988 label: "clippy::manual_ok_or",
5989 description: r##"Finds patterns that reimplement `Option::ok_or`."##,
5990 },
5991 Lint {
5992 label: "clippy::manual_range_contains",
5993 description: r##"Checks for expressions like `x >= 3 && x < 8` that could
5994be more readably expressed as `(3..8).contains(x)`."##,
5995 },
5996 Lint {
5997 label: "clippy::manual_saturating_arithmetic",
5998 description: r##"Checks for `.checked_add/sub(x).unwrap_or(MAX/MIN)`."##,
5999 },
6000 Lint {
6001 label: "clippy::manual_str_repeat",
6002 description: r##"Checks for manual implementations of `str::repeat`"##,
6003 },
6004 Lint {
6005 label: "clippy::manual_strip",
6006 description: r##"Suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing using
6007the pattern's length."##,
6008 },
6009 Lint { label: "clippy::manual_swap", description: r##"Checks for manual swapping."## },
6010 Lint {
6011 label: "clippy::manual_unwrap_or",
6012 description: r##"Finds patterns that reimplement `Option::unwrap_or` or `Result::unwrap_or`."##,
6013 },
6014 Lint {
6015 label: "clippy::many_single_char_names",
6016 description: r##"Checks for too many variables whose name consists of a
6017single character."##,
6018 },
6019 Lint {
6020 label: "clippy::map_clone",
6021 description: r##"Checks for usage of `map(|x| x.clone())` or
6022dereferencing closures for `Copy` types, on `Iterator` or `Option`,
6023and suggests `cloned()` or `copied()` instead"##,
6024 },
6025 Lint {
6026 label: "clippy::map_collect_result_unit",
6027 description: r##"Checks for usage of `_.map(_).collect::<Result<(), _>()`."##,
6028 },
6029 Lint {
6030 label: "clippy::map_entry",
6031 description: r##"Checks for uses of `contains_key` + `insert` on `HashMap`
6032or `BTreeMap`."##,
6033 },
6034 Lint {
6035 label: "clippy::map_err_ignore",
6036 description: r##"Checks for instances of `map_err(|_| Some::Enum)`"##,
6037 },
6038 Lint {
6039 label: "clippy::map_flatten",
6040 description: r##"Checks for usage of `_.map(_).flatten(_)` on `Iterator` and `Option`"##,
6041 },
6042 Lint {
6043 label: "clippy::map_identity",
6044 description: r##"Checks for instances of `map(f)` where `f` is the identity function."##,
6045 },
6046 Lint {
6047 label: "clippy::map_unwrap_or",
6048 description: r##"Checks for usage of `option.map(_).unwrap_or(_)` or `option.map(_).unwrap_or_else(_)` or
6049`result.map(_).unwrap_or_else(_)`."##,
6050 },
6051 Lint {
6052 label: "clippy::match_as_ref",
6053 description: r##"Checks for match which is used to add a reference to an
6054`Option` value."##,
6055 },
6056 Lint {
6057 label: "clippy::match_bool",
6058 description: r##"Checks for matches where match expression is a `bool`. It
6059suggests to replace the expression with an `if...else` block."##,
6060 },
6061 Lint {
6062 label: "clippy::match_like_matches_macro",
6063 description: r##"Checks for `match` or `if let` expressions producing a
6064`bool` that could be written using `matches!`"##,
6065 },
6066 Lint {
6067 label: "clippy::match_on_vec_items",
6068 description: r##"Checks for `match vec[idx]` or `match vec[n..m]`."##,
6069 },
6070 Lint {
6071 label: "clippy::match_overlapping_arm",
6072 description: r##"Checks for overlapping match arms."##,
6073 },
6074 Lint {
6075 label: "clippy::match_ref_pats",
6076 description: r##"Checks for matches where all arms match a reference,
6077suggesting to remove the reference and deref the matched expression
6078instead. It also checks for `if let &foo = bar` blocks."##,
6079 },
6080 Lint {
6081 label: "clippy::match_same_arms",
6082 description: r##"Checks for `match` with identical arm bodies."##,
6083 },
6084 Lint {
6085 label: "clippy::match_single_binding",
6086 description: r##"Checks for useless match that binds to only one value."##,
6087 },
6088 Lint {
6089 label: "clippy::match_wild_err_arm",
6090 description: r##"Checks for arm which matches all errors with `Err(_)`
6091and take drastic actions like `panic!`."##,
6092 },
6093 Lint {
6094 label: "clippy::match_wildcard_for_single_variants",
6095 description: r##"Checks for wildcard enum matches for a single variant."##,
6096 },
6097 Lint {
6098 label: "clippy::maybe_infinite_iter",
6099 description: r##"Checks for iteration that may be infinite."##,
6100 },
6101 Lint {
6102 label: "clippy::mem_discriminant_non_enum",
6103 description: r##"Checks for calls of `mem::discriminant()` on a non-enum type."##,
6104 },
6105 Lint {
6106 label: "clippy::mem_forget",
6107 description: r##"Checks for usage of `std::mem::forget(t)` where `t` is
6108`Drop`."##,
6109 },
6110 Lint {
6111 label: "clippy::mem_replace_option_with_none",
6112 description: r##"Checks for `mem::replace()` on an `Option` with
6113`None`."##,
6114 },
6115 Lint {
6116 label: "clippy::mem_replace_with_default",
6117 description: r##"Checks for `std::mem::replace` on a value of type
6118`T` with `T::default()`."##,
6119 },
6120 Lint {
6121 label: "clippy::mem_replace_with_uninit",
6122 description: r##"Checks for `mem::replace(&mut _, mem::uninitialized())`
6123and `mem::replace(&mut _, mem::zeroed())`."##,
6124 },
6125 Lint {
6126 label: "clippy::min_max",
6127 description: r##"Checks for expressions where `std::cmp::min` and `max` are
6128used to clamp values, but switched so that the result is constant."##,
6129 },
6130 Lint {
6131 label: "clippy::misaligned_transmute",
6132 description: r##"Nothing. This lint has been deprecated."##,
6133 },
6134 Lint {
6135 label: "clippy::mismatched_target_os",
6136 description: r##"Checks for cfg attributes having operating systems used in target family position."##,
6137 },
6138 Lint {
6139 label: "clippy::misrefactored_assign_op",
6140 description: r##"Checks for `a op= a op b` or `a op= b op a` patterns."##,
6141 },
6142 Lint {
6143 label: "clippy::missing_const_for_fn",
6144 description: r##"Suggests the use of `const` in functions and methods where possible."##,
6145 },
6146 Lint {
6147 label: "clippy::missing_docs_in_private_items",
6148 description: r##"Warns if there is missing doc for any documentable item
6149(public or private)."##,
6150 },
6151 Lint {
6152 label: "clippy::missing_errors_doc",
6153 description: r##"Checks the doc comments of publicly visible functions that
6154return a `Result` type and warns if there is no `# Errors` section."##,
6155 },
6156 Lint {
6157 label: "clippy::missing_inline_in_public_items",
6158 description: r##"it lints if an exported function, method, trait method with default impl,
6159or trait method impl is not `#[inline]`."##,
6160 },
6161 Lint {
6162 label: "clippy::missing_panics_doc",
6163 description: r##"Checks the doc comments of publicly visible functions that
6164may panic and warns if there is no `# Panics` section."##,
6165 },
6166 Lint {
6167 label: "clippy::missing_safety_doc",
6168 description: r##"Checks for the doc comments of publicly visible
6169unsafe functions and warns if there is no `# Safety` section."##,
6170 },
6171 Lint {
6172 label: "clippy::mistyped_literal_suffixes",
6173 description: r##"Warns for mistyped suffix in literals"##,
6174 },
6175 Lint {
6176 label: "clippy::mixed_case_hex_literals",
6177 description: r##"Warns on hexadecimal literals with mixed-case letter
6178digits."##,
6179 },
6180 Lint {
6181 label: "clippy::module_inception",
6182 description: r##"Checks for modules that have the same name as their
6183parent module"##,
6184 },
6185 Lint {
6186 label: "clippy::module_name_repetitions",
6187 description: r##"Detects type names that are prefixed or suffixed by the
6188containing module's name."##,
6189 },
6190 Lint { label: "clippy::modulo_arithmetic", description: r##"Checks for modulo arithmetic."## },
6191 Lint {
6192 label: "clippy::modulo_one",
6193 description: r##"Checks for getting the remainder of a division by one or minus
6194one."##,
6195 },
6196 Lint {
6197 label: "clippy::multiple_crate_versions",
6198 description: r##"Checks to see if multiple versions of a crate are being
6199used."##,
6200 },
6201 Lint {
6202 label: "clippy::multiple_inherent_impl",
6203 description: r##"Checks for multiple inherent implementations of a struct"##,
6204 },
6205 Lint {
6206 label: "clippy::must_use_candidate",
6207 description: r##"Checks for public functions that have no
6208[`#[must_use]`] attribute, but return something not already marked
6209must-use, have no mutable arg and mutate no statics.
6210
6211[`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute"##,
6212 },
6213 Lint {
6214 label: "clippy::must_use_unit",
6215 description: r##"Checks for a [`#[must_use]`] attribute on
6216unit-returning functions and methods.
6217
6218[`#[must_use]`]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute"##,
6219 },
6220 Lint {
6221 label: "clippy::mut_from_ref",
6222 description: r##"This lint checks for functions that take immutable
6223references and return mutable ones."##,
6224 },
6225 Lint {
6226 label: "clippy::mut_mut",
6227 description: r##"Checks for instances of `mut mut` references."##,
6228 },
6229 Lint {
6230 label: "clippy::mut_mutex_lock",
6231 description: r##"Checks for `&mut Mutex::lock` calls"##,
6232 },
6233 Lint {
6234 label: "clippy::mut_range_bound",
6235 description: r##"Checks for loops which have a range bound that is a mutable variable"##,
6236 },
6237 Lint {
6238 label: "clippy::mutable_key_type",
6239 description: r##"Checks for sets/maps with mutable key types."##,
6240 },
6241 Lint {
6242 label: "clippy::mutex_atomic",
6243 description: r##"Checks for usages of `Mutex<X>` where an atomic will do."##,
6244 },
6245 Lint {
6246 label: "clippy::mutex_integer",
6247 description: r##"Checks for usages of `Mutex<X>` where `X` is an integral
6248type."##,
6249 },
6250 Lint { label: "clippy::naive_bytecount", description: r##"Checks for naive byte counts"## },
6251 Lint {
6252 label: "clippy::needless_arbitrary_self_type",
6253 description: r##"The lint checks for `self` in fn parameters that
6254specify the `Self`-type explicitly"##,
6255 },
6256 Lint {
6257 label: "clippy::needless_bitwise_bool",
6258 description: r##"Checks for uses of bitwise and/or operators between booleans, where performance may be improved by using
6259a lazy and."##,
6260 },
6261 Lint {
6262 label: "clippy::needless_bool",
6263 description: r##"Checks for expressions of the form `if c { true } else {
6264false }` (or vice versa) and suggests using the condition directly."##,
6265 },
6266 Lint {
6267 label: "clippy::needless_borrow",
6268 description: r##"Checks for address of operations (`&`) that are going to
6269be dereferenced immediately by the compiler."##,
6270 },
6271 Lint {
6272 label: "clippy::needless_borrowed_reference",
6273 description: r##"Checks for bindings that destructure a reference and borrow the inner
6274value with `&ref`."##,
6275 },
6276 Lint {
6277 label: "clippy::needless_collect",
6278 description: r##"Checks for functions collecting an iterator when collect
6279is not needed."##,
6280 },
6281 Lint {
6282 label: "clippy::needless_continue",
6283 description: r##"The lint checks for `if`-statements appearing in loops
6284that contain a `continue` statement in either their main blocks or their
6285`else`-blocks, when omitting the `else`-block possibly with some
6286rearrangement of code can make the code easier to understand."##,
6287 },
6288 Lint {
6289 label: "clippy::needless_doctest_main",
6290 description: r##"Checks for `fn main() { .. }` in doctests"##,
6291 },
6292 Lint {
6293 label: "clippy::needless_for_each",
6294 description: r##"Checks for usage of `for_each` that would be more simply written as a
6295`for` loop."##,
6296 },
6297 Lint {
6298 label: "clippy::needless_lifetimes",
6299 description: r##"Checks for lifetime annotations which can be removed by
6300relying on lifetime elision."##,
6301 },
6302 Lint {
6303 label: "clippy::needless_pass_by_value",
6304 description: r##"Checks for functions taking arguments by value, but not
6305consuming them in its
6306body."##,
6307 },
6308 Lint {
6309 label: "clippy::needless_question_mark",
6310 description: r##"Suggests alternatives for useless applications of `?` in terminating expressions"##,
6311 },
6312 Lint {
6313 label: "clippy::needless_range_loop",
6314 description: r##"Checks for looping over the range of `0..len` of some
6315collection just to get the values by index."##,
6316 },
6317 Lint {
6318 label: "clippy::needless_return",
6319 description: r##"Checks for return statements at the end of a block."##,
6320 },
6321 Lint {
6322 label: "clippy::needless_update",
6323 description: r##"Checks for needlessly including a base struct on update
6324when all fields are changed anyway.
6325
6326This lint is not applied to structs marked with
6327[non_exhaustive](https://doc.rust-lang.org/reference/attributes/type_system.html)."##,
6328 },
6329 Lint {
6330 label: "clippy::neg_cmp_op_on_partial_ord",
6331 description: r##"Checks for the usage of negated comparison operators on types which only implement
6332`PartialOrd` (e.g., `f64`)."##,
6333 },
6334 Lint {
6335 label: "clippy::neg_multiply",
6336 description: r##"Checks for multiplication by -1 as a form of negation."##,
6337 },
6338 Lint {
6339 label: "clippy::never_loop",
6340 description: r##"Checks for loops that will always `break`, `return` or
6341`continue` an outer loop."##,
6342 },
6343 Lint {
6344 label: "clippy::new_ret_no_self",
6345 description: r##"Checks for `new` not returning a type that contains `Self`."##,
6346 },
6347 Lint {
6348 label: "clippy::new_without_default",
6349 description: r##"Checks for types with a `fn new() -> Self` method and no
6350implementation of
6351[`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)."##,
6352 },
6353 Lint {
6354 label: "clippy::no_effect",
6355 description: r##"Checks for statements which have no effect."##,
6356 },
6357 Lint {
6358 label: "clippy::non_ascii_literal",
6359 description: r##"Checks for non-ASCII characters in string literals."##,
6360 },
6361 Lint {
6362 label: "clippy::non_octal_unix_permissions",
6363 description: r##"Checks for non-octal values used to set Unix file permissions."##,
6364 },
6365 Lint {
6366 label: "clippy::nonminimal_bool",
6367 description: r##"Checks for boolean expressions that can be written more
6368concisely."##,
6369 },
6370 Lint {
6371 label: "clippy::nonsensical_open_options",
6372 description: r##"Checks for duplicate open options as well as combinations
6373that make no sense."##,
6374 },
6375 Lint {
6376 label: "clippy::not_unsafe_ptr_arg_deref",
6377 description: r##"Checks for public functions that dereference raw pointer
6378arguments but are not marked `unsafe`."##,
6379 },
6380 Lint { label: "clippy::ok_expect", description: r##"Checks for usage of `ok().expect(..)`."## },
6381 Lint {
6382 label: "clippy::op_ref",
6383 description: r##"Checks for arguments to `==` which have their address
6384taken to satisfy a bound
6385and suggests to dereference the other argument instead"##,
6386 },
6387 Lint {
6388 label: "clippy::option_as_ref_deref",
6389 description: r##"Checks for usage of `_.as_ref().map(Deref::deref)` or it's aliases (such as String::as_str)."##,
6390 },
6391 Lint {
6392 label: "clippy::option_env_unwrap",
6393 description: r##"Checks for usage of `option_env!(...).unwrap()` and
6394suggests usage of the `env!` macro."##,
6395 },
6396 Lint {
6397 label: "clippy::option_filter_map",
6398 description: r##"Checks for indirect collection of populated `Option`"##,
6399 },
6400 Lint {
6401 label: "clippy::option_if_let_else",
6402 description: r##"Lints usage of `if let Some(v) = ... { y } else { x }` which is more
6403idiomatically done with `Option::map_or` (if the else bit is a pure
6404expression) or `Option::map_or_else` (if the else bit is an impure
6405expression)."##,
6406 },
6407 Lint {
6408 label: "clippy::option_map_or_none",
6409 description: r##"Checks for usage of `_.map_or(None, _)`."##,
6410 },
6411 Lint {
6412 label: "clippy::option_map_unit_fn",
6413 description: r##"Checks for usage of `option.map(f)` where f is a function
6414or closure that returns the unit type `()`."##,
6415 },
6416 Lint {
6417 label: "clippy::option_option",
6418 description: r##"Checks for use of `Option<Option<_>>` in function signatures and type
6419definitions"##,
6420 },
6421 Lint {
6422 label: "clippy::or_fun_call",
6423 description: r##"Checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`,
6424etc., and suggests to use `or_else`, `unwrap_or_else`, etc., or
6425`unwrap_or_default` instead."##,
6426 },
6427 Lint {
6428 label: "clippy::out_of_bounds_indexing",
6429 description: r##"Checks for out of bounds array indexing with a constant
6430index."##,
6431 },
6432 Lint {
6433 label: "clippy::overflow_check_conditional",
6434 description: r##"Detects classic underflow/overflow checks."##,
6435 },
6436 Lint { label: "clippy::panic", description: r##"Checks for usage of `panic!`."## },
6437 Lint {
6438 label: "clippy::panic_in_result_fn",
6439 description: r##"Checks for usage of `panic!`, `unimplemented!`, `todo!`, `unreachable!` or assertions in a function of type result."##,
6440 },
6441 Lint {
6442 label: "clippy::panicking_unwrap",
6443 description: r##"Checks for calls of `unwrap[_err]()` that will always fail."##,
6444 },
6445 Lint {
6446 label: "clippy::partialeq_ne_impl",
6447 description: r##"Checks for manual re-implementations of `PartialEq::ne`."##,
6448 },
6449 Lint {
6450 label: "clippy::path_buf_push_overwrite",
6451 description: r##"* Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push)
6452calls on `PathBuf` that can cause overwrites."##,
6453 },
6454 Lint {
6455 label: "clippy::pattern_type_mismatch",
6456 description: r##"Checks for patterns that aren't exact representations of the types
6457they are applied to.
6458
6459To satisfy this lint, you will have to adjust either the expression that is matched
6460against or the pattern itself, as well as the bindings that are introduced by the
6461adjusted patterns. For matching you will have to either dereference the expression
6462with the `*` operator, or amend the patterns to explicitly match against `&<pattern>`
6463or `&mut <pattern>` depending on the reference mutability. For the bindings you need
6464to use the inverse. You can leave them as plain bindings if you wish for the value
6465to be copied, but you must use `ref mut <variable>` or `ref <variable>` to construct
6466a reference into the matched structure.
6467
6468If you are looking for a way to learn about ownership semantics in more detail, it
6469is recommended to look at IDE options available to you to highlight types, lifetimes
6470and reference semantics in your code. The available tooling would expose these things
6471in a general way even outside of the various pattern matching mechanics. Of course
6472this lint can still be used to highlight areas of interest and ensure a good understanding
6473of ownership semantics."##,
6474 },
6475 Lint {
6476 label: "clippy::possible_missing_comma",
6477 description: r##"Checks for possible missing comma in an array. It lints if
6478an array element is a binary operator expression and it lies on two lines."##,
6479 },
6480 Lint {
6481 label: "clippy::precedence",
6482 description: r##"Checks for operations where precedence may be unclear
6483and suggests to add parentheses. Currently it catches the following:
6484* mixed usage of arithmetic and bit shifting/combining operators without
6485parentheses
6486* a negative numeric literal (which is really a unary `-` followed by a
6487numeric literal)
6488 followed by a method call"##,
6489 },
6490 Lint {
6491 label: "clippy::print_literal",
6492 description: r##"This lint warns about the use of literals as `print!`/`println!` args."##,
6493 },
6494 Lint {
6495 label: "clippy::print_stderr",
6496 description: r##"Checks for printing on *stderr*. The purpose of this lint
6497is to catch debugging remnants."##,
6498 },
6499 Lint {
6500 label: "clippy::print_stdout",
6501 description: r##"Checks for printing on *stdout*. The purpose of this lint
6502is to catch debugging remnants."##,
6503 },
6504 Lint {
6505 label: "clippy::print_with_newline",
6506 description: r##"This lint warns when you use `print!()` with a format
6507string that ends in a newline."##,
6508 },
6509 Lint {
6510 label: "clippy::println_empty_string",
6511 description: r##"This lint warns when you use `println!()` to
6512print a newline."##,
6513 },
6514 Lint {
6515 label: "clippy::ptr_arg",
6516 description: r##"This lint checks for function arguments of type `&String`
6517or `&Vec` unless the references are mutable. It will also suggest you
6518replace `.clone()` calls with the appropriate `.to_owned()`/`to_string()`
6519calls."##,
6520 },
6521 Lint {
6522 label: "clippy::ptr_as_ptr",
6523 description: r##"Checks for `as` casts between raw pointers without changing its mutability,
6524namely `*const T` to `*const U` and `*mut T` to `*mut U`."##,
6525 },
6526 Lint { label: "clippy::ptr_eq", description: r##"Use `std::ptr::eq` when applicable"## },
6527 Lint {
6528 label: "clippy::ptr_offset_with_cast",
6529 description: r##"Checks for usage of the `offset` pointer method with a `usize` casted to an
6530`isize`."##,
6531 },
6532 Lint {
6533 label: "clippy::pub_enum_variant_names",
6534 description: r##"Nothing. This lint has been deprecated."##,
6535 },
6536 Lint {
6537 label: "clippy::question_mark",
6538 description: r##"Checks for expressions that could be replaced by the question mark operator."##,
6539 },
6540 Lint {
6541 label: "clippy::range_minus_one",
6542 description: r##"Checks for inclusive ranges where 1 is subtracted from
6543the upper bound, e.g., `x..=(y-1)`."##,
6544 },
6545 Lint {
6546 label: "clippy::range_plus_one",
6547 description: r##"Checks for exclusive ranges where 1 is added to the
6548upper bound, e.g., `x..(y+1)`."##,
6549 },
6550 Lint {
6551 label: "clippy::range_step_by_zero",
6552 description: r##"Nothing. This lint has been deprecated."##,
6553 },
6554 Lint {
6555 label: "clippy::range_zip_with_len",
6556 description: r##"Checks for zipping a collection with the range of
6557`0.._.len()`."##,
6558 },
6559 Lint {
6560 label: "clippy::rc_buffer",
6561 description: r##"Checks for `Rc<T>` and `Arc<T>` when `T` is a mutable buffer type such as `String` or `Vec`."##,
6562 },
6563 Lint {
6564 label: "clippy::redundant_allocation",
6565 description: r##"Checks for use of redundant allocations anywhere in the code."##,
6566 },
6567 Lint {
6568 label: "clippy::redundant_clone",
6569 description: r##"Checks for a redundant `clone()` (and its relatives) which clones an owned
6570value that is going to be dropped without further use."##,
6571 },
6572 Lint {
6573 label: "clippy::redundant_closure",
6574 description: r##"Checks for closures which just call another function where
6575the function can be called directly. `unsafe` functions or calls where types
6576get adjusted are ignored."##,
6577 },
6578 Lint {
6579 label: "clippy::redundant_closure_call",
6580 description: r##"Detects closures called in the same expression where they
6581are defined."##,
6582 },
6583 Lint {
6584 label: "clippy::redundant_closure_for_method_calls",
6585 description: r##"Checks for closures which only invoke a method on the closure
6586argument and can be replaced by referencing the method directly."##,
6587 },
6588 Lint {
6589 label: "clippy::redundant_else",
6590 description: r##"Checks for `else` blocks that can be removed without changing semantics."##,
6591 },
6592 Lint {
6593 label: "clippy::redundant_field_names",
6594 description: r##"Checks for fields in struct literals where shorthands
6595could be used."##,
6596 },
6597 Lint {
6598 label: "clippy::redundant_pattern",
6599 description: r##"Checks for patterns in the form `name @ _`."##,
6600 },
6601 Lint {
6602 label: "clippy::redundant_pattern_matching",
6603 description: r##"Lint for redundant pattern matching over `Result`, `Option`,
6604`std::task::Poll` or `std::net::IpAddr`"##,
6605 },
6606 Lint {
6607 label: "clippy::redundant_pub_crate",
6608 description: r##"Checks for items declared `pub(crate)` that are not crate visible because they
6609are inside a private module."##,
6610 },
6611 Lint {
6612 label: "clippy::redundant_slicing",
6613 description: r##"Checks for redundant slicing expressions which use the full range, and
6614do not change the type."##,
6615 },
6616 Lint {
6617 label: "clippy::redundant_static_lifetimes",
6618 description: r##"Checks for constants and statics with an explicit `'static` lifetime."##,
6619 },
6620 Lint {
6621 label: "clippy::ref_binding_to_reference",
6622 description: r##"Checks for `ref` bindings which create a reference to a reference."##,
6623 },
6624 Lint {
6625 label: "clippy::ref_in_deref",
6626 description: r##"Checks for references in expressions that use
6627auto dereference."##,
6628 },
6629 Lint {
6630 label: "clippy::ref_option_ref",
6631 description: r##"Checks for usage of `&Option<&T>`."##,
6632 },
6633 Lint {
6634 label: "clippy::regex_macro",
6635 description: r##"Nothing. This lint has been deprecated."##,
6636 },
6637 Lint {
6638 label: "clippy::repeat_once",
6639 description: r##"Checks for usage of `.repeat(1)` and suggest the following method for each types.
6640- `.to_string()` for `str`
6641- `.clone()` for `String`
6642- `.to_vec()` for `slice`"##,
6643 },
6644 Lint {
6645 label: "clippy::replace_consts",
6646 description: r##"Nothing. This lint has been deprecated."##,
6647 },
6648 Lint {
6649 label: "clippy::rest_pat_in_fully_bound_structs",
6650 description: r##"Checks for unnecessary '..' pattern binding on struct when all fields are explicitly matched."##,
6651 },
6652 Lint {
6653 label: "clippy::result_map_or_into_option",
6654 description: r##"Checks for usage of `_.map_or(None, Some)`."##,
6655 },
6656 Lint {
6657 label: "clippy::result_map_unit_fn",
6658 description: r##"Checks for usage of `result.map(f)` where f is a function
6659or closure that returns the unit type `()`."##,
6660 },
6661 Lint {
6662 label: "clippy::result_unit_err",
6663 description: r##"Checks for public functions that return a `Result`
6664with an `Err` type of `()`. It suggests using a custom type that
6665implements `std::error::Error`."##,
6666 },
6667 Lint {
6668 label: "clippy::reversed_empty_ranges",
6669 description: r##"Checks for range expressions `x..y` where both `x` and `y`
6670are constant and `x` is greater or equal to `y`."##,
6671 },
6672 Lint {
6673 label: "clippy::same_functions_in_if_condition",
6674 description: r##"Checks for consecutive `if`s with the same function call."##,
6675 },
6676 Lint {
6677 label: "clippy::same_item_push",
6678 description: r##"Checks whether a for loop is being used to push a constant
6679value into a Vec."##,
6680 },
6681 Lint {
6682 label: "clippy::search_is_some",
6683 description: r##"Checks for an iterator or string search (such as `find()`,
6684`position()`, or `rposition()`) followed by a call to `is_some()` or `is_none()`."##,
6685 },
6686 Lint {
6687 label: "clippy::self_assignment",
6688 description: r##"Checks for explicit self-assignments."##,
6689 },
6690 Lint {
6691 label: "clippy::semicolon_if_nothing_returned",
6692 description: r##"Looks for blocks of expressions and fires if the last expression returns
6693`()` but is not followed by a semicolon."##,
6694 },
6695 Lint {
6696 label: "clippy::serde_api_misuse",
6697 description: r##"Checks for mis-uses of the serde API."##,
6698 },
6699 Lint {
6700 label: "clippy::shadow_reuse",
6701 description: r##"Checks for bindings that shadow other bindings already in
6702scope, while reusing the original value."##,
6703 },
6704 Lint {
6705 label: "clippy::shadow_same",
6706 description: r##"Checks for bindings that shadow other bindings already in
6707scope, while just changing reference level or mutability."##,
6708 },
6709 Lint {
6710 label: "clippy::shadow_unrelated",
6711 description: r##"Checks for bindings that shadow other bindings already in
6712scope, either without a initialization or with one that does not even use
6713the original value."##,
6714 },
6715 Lint {
6716 label: "clippy::short_circuit_statement",
6717 description: r##"Checks for the use of short circuit boolean conditions as
6718a
6719statement."##,
6720 },
6721 Lint {
6722 label: "clippy::should_assert_eq",
6723 description: r##"Nothing. This lint has been deprecated."##,
6724 },
6725 Lint {
6726 label: "clippy::should_implement_trait",
6727 description: r##"Checks for methods that should live in a trait
6728implementation of a `std` trait (see [llogiq's blog
6729post](http://llogiq.github.io/2015/07/30/traits.html) for further
6730information) instead of an inherent implementation."##,
6731 },
6732 Lint {
6733 label: "clippy::similar_names",
6734 description: r##"Checks for names that are very similar and thus confusing."##,
6735 },
6736 Lint {
6737 label: "clippy::single_char_add_str",
6738 description: r##"Warns when using `push_str`/`insert_str` with a single-character string literal
6739where `push`/`insert` with a `char` would work fine."##,
6740 },
6741 Lint {
6742 label: "clippy::single_char_pattern",
6743 description: r##"Checks for string methods that receive a single-character
6744`str` as an argument, e.g., `_.split(x)`."##,
6745 },
6746 Lint {
6747 label: "clippy::single_component_path_imports",
6748 description: r##"Checking for imports with single component use path."##,
6749 },
6750 Lint {
6751 label: "clippy::single_element_loop",
6752 description: r##"Checks whether a for loop has a single element."##,
6753 },
6754 Lint {
6755 label: "clippy::single_match",
6756 description: r##"Checks for matches with a single arm where an `if let`
6757will usually suffice."##,
6758 },
6759 Lint {
6760 label: "clippy::single_match_else",
6761 description: r##"Checks for matches with two arms where an `if let else` will
6762usually suffice."##,
6763 },
6764 Lint {
6765 label: "clippy::size_of_in_element_count",
6766 description: r##"Detects expressions where
6767`size_of::<T>` or `size_of_val::<T>` is used as a
6768count of elements of type `T`"##,
6769 },
6770 Lint {
6771 label: "clippy::skip_while_next",
6772 description: r##"Checks for usage of `_.skip_while(condition).next()`."##,
6773 },
6774 Lint {
6775 label: "clippy::slow_vector_initialization",
6776 description: r##"Checks slow zero-filled vector initialization"##,
6777 },
6778 Lint {
6779 label: "clippy::stable_sort_primitive",
6780 description: r##"When sorting primitive values (integers, bools, chars, as well
6781as arrays, slices, and tuples of such items), it is better to
6782use an unstable sort than a stable sort."##,
6783 },
6784 Lint {
6785 label: "clippy::str_to_string",
6786 description: r##"This lint checks for `.to_string()` method calls on values of type `&str`."##,
6787 },
6788 Lint {
6789 label: "clippy::string_add",
6790 description: r##"Checks for all instances of `x + _` where `x` is of type
6791`String`, but only if [`string_add_assign`](#string_add_assign) does *not*
6792match."##,
6793 },
6794 Lint {
6795 label: "clippy::string_add_assign",
6796 description: r##"Checks for string appends of the form `x = x + y` (without
6797`let`!)."##,
6798 },
6799 Lint {
6800 label: "clippy::string_extend_chars",
6801 description: r##"Checks for the use of `.extend(s.chars())` where s is a
6802`&str` or `String`."##,
6803 },
6804 Lint {
6805 label: "clippy::string_from_utf8_as_bytes",
6806 description: r##"Check if the string is transformed to byte array and casted back to string."##,
6807 },
6808 Lint {
6809 label: "clippy::string_lit_as_bytes",
6810 description: r##"Checks for the `as_bytes` method called on string literals
6811that contain only ASCII characters."##,
6812 },
6813 Lint {
6814 label: "clippy::string_to_string",
6815 description: r##"This lint checks for `.to_string()` method calls on values of type `String`."##,
6816 },
6817 Lint {
6818 label: "clippy::struct_excessive_bools",
6819 description: r##"Checks for excessive
6820use of bools in structs."##,
6821 },
6822 Lint {
6823 label: "clippy::suboptimal_flops",
6824 description: r##"Looks for floating-point expressions that
6825can be expressed using built-in methods to improve both
6826accuracy and performance."##,
6827 },
6828 Lint {
6829 label: "clippy::suspicious_arithmetic_impl",
6830 description: r##"Lints for suspicious operations in impls of arithmetic operators, e.g.
6831subtracting elements in an Add impl."##,
6832 },
6833 Lint {
6834 label: "clippy::suspicious_assignment_formatting",
6835 description: r##"Checks for use of the non-existent `=*`, `=!` and `=-`
6836operators."##,
6837 },
6838 Lint {
6839 label: "clippy::suspicious_else_formatting",
6840 description: r##"Checks for formatting of `else`. It lints if the `else`
6841is followed immediately by a newline or the `else` seems to be missing."##,
6842 },
6843 Lint {
6844 label: "clippy::suspicious_map",
6845 description: r##"Checks for calls to `map` followed by a `count`."##,
6846 },
6847 Lint {
6848 label: "clippy::suspicious_op_assign_impl",
6849 description: r##"Lints for suspicious operations in impls of OpAssign, e.g.
6850subtracting elements in an AddAssign impl."##,
6851 },
6852 Lint {
6853 label: "clippy::suspicious_operation_groupings",
6854 description: r##"Checks for unlikely usages of binary operators that are almost
6855certainly typos and/or copy/paste errors, given the other usages
6856of binary operators nearby."##,
6857 },
6858 Lint {
6859 label: "clippy::suspicious_splitn",
6860 description: r##"Checks for calls to [`splitn`]
6861(https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and
6862related functions with either zero or one splits."##,
6863 },
6864 Lint {
6865 label: "clippy::suspicious_unary_op_formatting",
6866 description: r##"Checks the formatting of a unary operator on the right hand side
6867of a binary operator. It lints if there is no space between the binary and unary operators,
6868but there is a space between the unary and its operand."##,
6869 },
6870 Lint {
6871 label: "clippy::tabs_in_doc_comments",
6872 description: r##"Checks doc comments for usage of tab characters."##,
6873 },
6874 Lint {
6875 label: "clippy::temporary_assignment",
6876 description: r##"Checks for construction of a structure or tuple just to
6877assign a value in it."##,
6878 },
6879 Lint {
6880 label: "clippy::to_digit_is_some",
6881 description: r##"Checks for `.to_digit(..).is_some()` on `char`s."##,
6882 },
6883 Lint {
6884 label: "clippy::to_string_in_display",
6885 description: r##"Checks for uses of `to_string()` in `Display` traits."##,
6886 },
6887 Lint { label: "clippy::todo", description: r##"Checks for usage of `todo!`."## },
6888 Lint {
6889 label: "clippy::too_many_arguments",
6890 description: r##"Checks for functions with too many parameters."##,
6891 },
6892 Lint {
6893 label: "clippy::too_many_lines",
6894 description: r##"Checks for functions with a large amount of lines."##,
6895 },
6896 Lint {
6897 label: "clippy::toplevel_ref_arg",
6898 description: r##"Checks for function arguments and let bindings denoted as
6899`ref`."##,
6900 },
6901 Lint {
6902 label: "clippy::trait_duplication_in_bounds",
6903 description: r##"Checks for cases where generics are being used and multiple
6904syntax specifications for trait bounds are used simultaneously."##,
6905 },
6906 Lint {
6907 label: "clippy::transmute_bytes_to_str",
6908 description: r##"Checks for transmutes from a `&[u8]` to a `&str`."##,
6909 },
6910 Lint {
6911 label: "clippy::transmute_float_to_int",
6912 description: r##"Checks for transmutes from a float to an integer."##,
6913 },
6914 Lint {
6915 label: "clippy::transmute_int_to_bool",
6916 description: r##"Checks for transmutes from an integer to a `bool`."##,
6917 },
6918 Lint {
6919 label: "clippy::transmute_int_to_char",
6920 description: r##"Checks for transmutes from an integer to a `char`."##,
6921 },
6922 Lint {
6923 label: "clippy::transmute_int_to_float",
6924 description: r##"Checks for transmutes from an integer to a float."##,
6925 },
6926 Lint {
6927 label: "clippy::transmute_ptr_to_ptr",
6928 description: r##"Checks for transmutes from a pointer to a pointer, or
6929from a reference to a reference."##,
6930 },
6931 Lint {
6932 label: "clippy::transmute_ptr_to_ref",
6933 description: r##"Checks for transmutes from a pointer to a reference."##,
6934 },
6935 Lint {
6936 label: "clippy::transmutes_expressible_as_ptr_casts",
6937 description: r##"Checks for transmutes that could be a pointer cast."##,
6938 },
6939 Lint {
6940 label: "clippy::transmuting_null",
6941 description: r##"Checks for transmute calls which would receive a null pointer."##,
6942 },
6943 Lint {
6944 label: "clippy::trivial_regex",
6945 description: r##"Checks for trivial [regex](https://crates.io/crates/regex)
6946creation (with `Regex::new`, `RegexBuilder::new`, or `RegexSet::new`)."##,
6947 },
6948 Lint {
6949 label: "clippy::trivially_copy_pass_by_ref",
6950 description: r##"Checks for functions taking arguments by reference, where
6951the argument type is `Copy` and small enough to be more efficient to always
6952pass by value."##,
6953 },
6954 Lint { label: "clippy::try_err", description: r##"Checks for usages of `Err(x)?`."## },
6955 Lint {
6956 label: "clippy::type_complexity",
6957 description: r##"Checks for types used in structs, parameters and `let`
6958declarations above a certain complexity threshold."##,
6959 },
6960 Lint {
6961 label: "clippy::type_repetition_in_bounds",
6962 description: r##"This lint warns about unnecessary type repetitions in trait bounds"##,
6963 },
6964 Lint {
6965 label: "clippy::undropped_manually_drops",
6966 description: r##"Prevents the safe `std::mem::drop` function from being called on `std::mem::ManuallyDrop`."##,
6967 },
6968 Lint {
6969 label: "clippy::unicode_not_nfc",
6970 description: r##"Checks for string literals that contain Unicode in a form
6971that is not equal to its
6972[NFC-recomposition](http://www.unicode.org/reports/tr15/#Norm_Forms)."##,
6973 },
6974 Lint {
6975 label: "clippy::unimplemented",
6976 description: r##"Checks for usage of `unimplemented!`."##,
6977 },
6978 Lint {
6979 label: "clippy::uninit_assumed_init",
6980 description: r##"Checks for `MaybeUninit::uninit().assume_init()`."##,
6981 },
6982 Lint {
6983 label: "clippy::unit_arg",
6984 description: r##"Checks for passing a unit value as an argument to a function without using a
6985unit literal (`()`)."##,
6986 },
6987 Lint {
6988 label: "clippy::unit_cmp",
6989 description: r##"Checks for comparisons to unit. This includes all binary
6990comparisons (like `==` and `<`) and asserts."##,
6991 },
6992 Lint {
6993 label: "clippy::unit_return_expecting_ord",
6994 description: r##"Checks for functions that expect closures of type
6995Fn(...) -> Ord where the implemented closure returns the unit type.
6996The lint also suggests to remove the semi-colon at the end of the statement if present."##,
6997 },
6998 Lint {
6999 label: "clippy::unnecessary_cast",
7000 description: r##"Checks for casts to the same type, casts of int literals to integer types
7001and casts of float literals to float types."##,
7002 },
7003 Lint {
7004 label: "clippy::unnecessary_filter_map",
7005 description: r##"Checks for `filter_map` calls which could be replaced by `filter` or `map`.
7006More specifically it checks if the closure provided is only performing one of the
7007filter or map operations and suggests the appropriate option."##,
7008 },
7009 Lint {
7010 label: "clippy::unnecessary_fold",
7011 description: r##"Checks for using `fold` when a more succinct alternative exists.
7012Specifically, this checks for `fold`s which could be replaced by `any`, `all`,
7013`sum` or `product`."##,
7014 },
7015 Lint {
7016 label: "clippy::unnecessary_lazy_evaluations",
7017 description: r##"As the counterpart to `or_fun_call`, this lint looks for unnecessary
7018lazily evaluated closures on `Option` and `Result`.
7019
7020This lint suggests changing the following functions, when eager evaluation results in
7021simpler code:
7022 - `unwrap_or_else` to `unwrap_or`
7023 - `and_then` to `and`
7024 - `or_else` to `or`
7025 - `get_or_insert_with` to `get_or_insert`
7026 - `ok_or_else` to `ok_or`"##,
7027 },
7028 Lint {
7029 label: "clippy::unnecessary_mut_passed",
7030 description: r##"Detects passing a mutable reference to a function that only
7031requires an immutable reference."##,
7032 },
7033 Lint {
7034 label: "clippy::unnecessary_operation",
7035 description: r##"Checks for expression statements that can be reduced to a
7036sub-expression."##,
7037 },
7038 Lint {
7039 label: "clippy::unnecessary_self_imports",
7040 description: r##"Checks for imports ending in `::{self}`."##,
7041 },
7042 Lint {
7043 label: "clippy::unnecessary_sort_by",
7044 description: r##"Detects uses of `Vec::sort_by` passing in a closure
7045which compares the two arguments, either directly or indirectly."##,
7046 },
7047 Lint {
7048 label: "clippy::unnecessary_unwrap",
7049 description: r##"Checks for calls of `unwrap[_err]()` that cannot fail."##,
7050 },
7051 Lint {
7052 label: "clippy::unnecessary_wraps",
7053 description: r##"Checks for private functions that only return `Ok` or `Some`."##,
7054 },
7055 Lint {
7056 label: "clippy::unneeded_field_pattern",
7057 description: r##"Checks for structure field patterns bound to wildcards."##,
7058 },
7059 Lint {
7060 label: "clippy::unneeded_wildcard_pattern",
7061 description: r##"Checks for tuple patterns with a wildcard
7062pattern (`_`) is next to a rest pattern (`..`).
7063
7064_NOTE_: While `_, ..` means there is at least one element left, `..`
7065means there are 0 or more elements left. This can make a difference
7066when refactoring, but shouldn't result in errors in the refactored code,
7067since the wildcard pattern isn't used anyway."##,
7068 },
7069 Lint {
7070 label: "clippy::unnested_or_patterns",
7071 description: r##"Checks for unnested or-patterns, e.g., `Some(0) | Some(2)` and
7072suggests replacing the pattern with a nested one, `Some(0 | 2)`.
7073
7074Another way to think of this is that it rewrites patterns in
7075*disjunctive normal form (DNF)* into *conjunctive normal form (CNF)*."##,
7076 },
7077 Lint { label: "clippy::unreachable", description: r##"Checks for usage of `unreachable!`."## },
7078 Lint {
7079 label: "clippy::unreadable_literal",
7080 description: r##"Warns if a long integral or floating-point constant does
7081not contain underscores."##,
7082 },
7083 Lint {
7084 label: "clippy::unsafe_derive_deserialize",
7085 description: r##"Checks for deriving `serde::Deserialize` on a type that
7086has methods using `unsafe`."##,
7087 },
7088 Lint {
7089 label: "clippy::unsafe_removed_from_name",
7090 description: r##"Checks for imports that remove unsafe from an item's
7091name."##,
7092 },
7093 Lint {
7094 label: "clippy::unsafe_vector_initialization",
7095 description: r##"Nothing. This lint has been deprecated."##,
7096 },
7097 Lint {
7098 label: "clippy::unseparated_literal_suffix",
7099 description: r##"Warns if literal suffixes are not separated by an
7100underscore."##,
7101 },
7102 Lint {
7103 label: "clippy::unsound_collection_transmute",
7104 description: r##"Checks for transmutes between collections whose
7105types have different ABI, size or alignment."##,
7106 },
7107 Lint {
7108 label: "clippy::unstable_as_mut_slice",
7109 description: r##"Nothing. This lint has been deprecated."##,
7110 },
7111 Lint {
7112 label: "clippy::unstable_as_slice",
7113 description: r##"Nothing. This lint has been deprecated."##,
7114 },
7115 Lint {
7116 label: "clippy::unused_async",
7117 description: r##"Checks for functions that are declared `async` but have no `.await`s inside of them."##,
7118 },
7119 Lint {
7120 label: "clippy::unused_collect",
7121 description: r##"Nothing. This lint has been deprecated."##,
7122 },
7123 Lint {
7124 label: "clippy::unused_io_amount",
7125 description: r##"Checks for unused written/read amount."##,
7126 },
7127 Lint {
7128 label: "clippy::unused_self",
7129 description: r##"Checks methods that contain a `self` argument but don't use it"##,
7130 },
7131 Lint {
7132 label: "clippy::unused_unit",
7133 description: r##"Checks for unit (`()`) expressions that can be removed."##,
7134 },
7135 Lint {
7136 label: "clippy::unusual_byte_groupings",
7137 description: r##"Warns if hexadecimal or binary literals are not grouped
7138by nibble or byte."##,
7139 },
7140 Lint {
7141 label: "clippy::unwrap_in_result",
7142 description: r##"Checks for functions of type Result that contain `expect()` or `unwrap()`"##,
7143 },
7144 Lint {
7145 label: "clippy::unwrap_used",
7146 description: r##"Checks for `.unwrap()` calls on `Option`s and on `Result`s."##,
7147 },
7148 Lint {
7149 label: "clippy::upper_case_acronyms",
7150 description: r##"Checks for fully capitalized names and optionally names containing a capitalized acronym."##,
7151 },
7152 Lint {
7153 label: "clippy::use_debug",
7154 description: r##"Checks for use of `Debug` formatting. The purpose of this
7155lint is to catch debugging remnants."##,
7156 },
7157 Lint {
7158 label: "clippy::use_self",
7159 description: r##"Checks for unnecessary repetition of structure name when a
7160replacement with `Self` is applicable."##,
7161 },
7162 Lint {
7163 label: "clippy::used_underscore_binding",
7164 description: r##"Checks for the use of bindings with a single leading
7165underscore."##,
7166 },
7167 Lint {
7168 label: "clippy::useless_asref",
7169 description: r##"Checks for usage of `.as_ref()` or `.as_mut()` where the
7170types before and after the call are the same."##,
7171 },
7172 Lint {
7173 label: "clippy::useless_attribute",
7174 description: r##"Checks for `extern crate` and `use` items annotated with
7175lint attributes.
7176
7177This lint permits `#[allow(unused_imports)]`, `#[allow(deprecated)]`,
7178`#[allow(unreachable_pub)]`, `#[allow(clippy::wildcard_imports)]` and
7179`#[allow(clippy::enum_glob_use)]` on `use` items and `#[allow(unused_imports)]` on
7180`extern crate` items with a `#[macro_use]` attribute."##,
7181 },
7182 Lint {
7183 label: "clippy::useless_conversion",
7184 description: r##"Checks for `Into`, `TryInto`, `From`, `TryFrom`, or `IntoIter` calls
7185which uselessly convert to the same type."##,
7186 },
7187 Lint {
7188 label: "clippy::useless_format",
7189 description: r##"Checks for the use of `format!(string literal with no
7190argument)` and `format!({}, foo)` where `foo` is a string."##,
7191 },
7192 Lint {
7193 label: "clippy::useless_let_if_seq",
7194 description: r##"Checks for variable declarations immediately followed by a
7195conditional affectation."##,
7196 },
7197 Lint {
7198 label: "clippy::useless_transmute",
7199 description: r##"Checks for transmutes to the original type of the object
7200and transmutes that could be a cast."##,
7201 },
7202 Lint {
7203 label: "clippy::useless_vec",
7204 description: r##"Checks for usage of `&vec![..]` when using `&[..]` would
7205be possible."##,
7206 },
7207 Lint {
7208 label: "clippy::vec_box",
7209 description: r##"Checks for use of `Vec<Box<T>>` where T: Sized anywhere in the code.
7210Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##,
7211 },
7212 Lint {
7213 label: "clippy::vec_init_then_push",
7214 description: r##"Checks for calls to `push` immediately after creating a new `Vec`."##,
7215 },
7216 Lint {
7217 label: "clippy::vec_resize_to_zero",
7218 description: r##"Finds occurrences of `Vec::resize(0, an_int)`"##,
7219 },
7220 Lint {
7221 label: "clippy::verbose_bit_mask",
7222 description: r##"Checks for bit masks that can be replaced by a call
7223to `trailing_zeros`"##,
7224 },
7225 Lint {
7226 label: "clippy::verbose_file_reads",
7227 description: r##"Checks for use of File::read_to_end and File::read_to_string."##,
7228 },
7229 Lint {
7230 label: "clippy::vtable_address_comparisons",
7231 description: r##"Checks for comparisons with an address of a trait vtable."##,
7232 },
7233 Lint {
7234 label: "clippy::while_immutable_condition",
7235 description: r##"Checks whether variables used within while loop condition
7236can be (and are) mutated in the body."##,
7237 },
7238 Lint {
7239 label: "clippy::while_let_loop",
7240 description: r##"Detects `loop + match` combinations that are easier
7241written as a `while let` loop."##,
7242 },
7243 Lint {
7244 label: "clippy::while_let_on_iterator",
7245 description: r##"Checks for `while let` expressions on iterators."##,
7246 },
7247 Lint {
7248 label: "clippy::wildcard_dependencies",
7249 description: r##"Checks for wildcard dependencies in the `Cargo.toml`."##,
7250 },
7251 Lint {
7252 label: "clippy::wildcard_enum_match_arm",
7253 description: r##"Checks for wildcard enum matches using `_`."##,
7254 },
7255 Lint {
7256 label: "clippy::wildcard_imports",
7257 description: r##"Checks for wildcard imports `use _::*`."##,
7258 },
7259 Lint {
7260 label: "clippy::wildcard_in_or_patterns",
7261 description: r##"Checks for wildcard pattern used with others patterns in same match arm."##,
7262 },
7263 Lint {
7264 label: "clippy::write_literal",
7265 description: r##"This lint warns about the use of literals as `write!`/`writeln!` args."##,
7266 },
7267 Lint {
7268 label: "clippy::write_with_newline",
7269 description: r##"This lint warns when you use `write!()` with a format
7270string that
7271ends in a newline."##,
7272 },
7273 Lint {
7274 label: "clippy::writeln_empty_string",
7275 description: r##"This lint warns when you use `writeln!(buf, )` to
7276print a newline."##,
7277 },
7278 Lint {
7279 label: "clippy::wrong_pub_self_convention",
7280 description: r##"Nothing. This lint has been deprecated."##,
7281 },
7282 Lint {
7283 label: "clippy::wrong_self_convention",
7284 description: r##"Checks for methods with certain name prefixes and which
7285doesn't match how self is taken. The actual rules are:
7286
7287|Prefix |Postfix |`self` taken | `self` type |
7288|-------|------------|-----------------------|--------------|
7289|`as_` | none |`&self` or `&mut self` | any |
7290|`from_`| none | none | any |
7291|`into_`| none |`self` | any |
7292|`is_` | none |`&self` or none | any |
7293|`to_` | `_mut` |`&mut self` | any |
7294|`to_` | not `_mut` |`self` | `Copy` |
7295|`to_` | not `_mut` |`&self` | not `Copy` |
7296
7297Note: Clippy doesn't trigger methods with `to_` prefix in:
7298- Traits definition.
7299Clippy can not tell if a type that implements a trait is `Copy` or not.
7300- Traits implementation, when `&self` is taken.
7301The method signature is controlled by the trait and often `&self` is required for all types that implement the trait
7302(see e.g. the `std::string::ToString` trait).
7303
7304Please find more info here:
7305https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv"##,
7306 },
7307 Lint {
7308 label: "clippy::wrong_transmute",
7309 description: r##"Checks for transmutes that can't ever be correct on any
7310architecture."##,
7311 },
7312 Lint { label: "clippy::zero_divided_by_zero", description: r##"Checks for `0.0 / 0.0`."## },
7313 Lint {
7314 label: "clippy::zero_prefixed_literal",
7315 description: r##"Warns if an integral constant literal starts with `0`."##,
7316 },
7317 Lint {
7318 label: "clippy::zero_ptr",
7319 description: r##"Catch casts from `0` to some pointer type"##,
7320 },
7321 Lint {
7322 label: "clippy::zero_sized_map_values",
7323 description: r##"Checks for maps with zero-sized value types anywhere in the code."##,
7324 },
7325 Lint {
7326 label: "clippy::zst_offset",
7327 description: r##"Checks for `offset(_)`, `wrapping_`{`add`, `sub`}, etc. on raw pointers to
7328zero-sized types"##,
7329 },
7330];
diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs
index ae52dd8bb..9634d872e 100644
--- a/crates/ide_db/src/helpers/import_assets.rs
+++ b/crates/ide_db/src/helpers/import_assets.rs
@@ -323,7 +323,7 @@ fn import_for_item(
323 } 323 }
324 324
325 let segment_import = 325 let segment_import =
326 find_import_for_segment(db, original_item_candidate, &unresolved_first_segment)?; 326 find_import_for_segment(db, original_item_candidate, unresolved_first_segment)?;
327 let trait_item_to_import = item_as_assoc(db, original_item) 327 let trait_item_to_import = item_as_assoc(db, original_item)
328 .and_then(|assoc| assoc.containing_trait(db)) 328 .and_then(|assoc| assoc.containing_trait(db))
329 .map(|trait_| ItemInNs::from(ModuleDef::from(trait_))); 329 .map(|trait_| ItemInNs::from(ModuleDef::from(trait_)));
@@ -383,7 +383,7 @@ fn find_import_for_segment(
383 original_item 383 original_item
384 } else { 384 } else {
385 let matching_module = 385 let matching_module =
386 module_with_segment_name(db, &unresolved_first_segment, original_item)?; 386 module_with_segment_name(db, unresolved_first_segment, original_item)?;
387 ItemInNs::from(ModuleDef::from(matching_module)) 387 ItemInNs::from(ModuleDef::from(matching_module))
388 }) 388 })
389} 389}
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs
index aa61c5bcb..10bbafe77 100644
--- a/crates/ide_db/src/helpers/insert_use.rs
+++ b/crates/ide_db/src/helpers/insert_use.rs
@@ -120,15 +120,19 @@ impl ImportScope {
120 if eq_visibility(prev_vis, curr_vis.clone()) && eq_attrs(prev_attrs, curr_attrs.clone()) 120 if eq_visibility(prev_vis, curr_vis.clone()) && eq_attrs(prev_attrs, curr_attrs.clone())
121 { 121 {
122 if let Some((prev_path, curr_path)) = prev.path().zip(curr.path()) { 122 if let Some((prev_path, curr_path)) = prev.path().zip(curr.path()) {
123 if let Some(_) = common_prefix(&prev_path, &curr_path) { 123 if let Some((prev_prefix, _)) = common_prefix(&prev_path, &curr_path) {
124 if prev.use_tree_list().is_none() && curr.use_tree_list().is_none() { 124 if prev.use_tree_list().is_none() && curr.use_tree_list().is_none() {
125 // Same prefix but no use tree lists so this has to be of item style. 125 let prefix_c = prev_prefix.qualifiers().count();
126 break ImportGranularityGuess::Item; // this overwrites CrateOrModule, technically the file doesn't adhere to anything here. 126 let curr_c = curr_path.qualifiers().count() - prefix_c;
127 } else { 127 let prev_c = prev_path.qualifiers().count() - prefix_c;
128 // Same prefix with item tree lists, has to be module style as it 128 if curr_c <= 1 || prev_c <= 1 {
129 // can't be crate style since the trees wouldn't share a prefix then. 129 // Same prefix but no use tree lists so this has to be of item style.
130 break ImportGranularityGuess::Module; 130 break ImportGranularityGuess::Item; // this overwrites CrateOrModule, technically the file doesn't adhere to anything here.
131 }
131 } 132 }
133 // Same prefix with item tree lists, has to be module style as it
134 // can't be crate style since the trees wouldn't share a prefix then.
135 break ImportGranularityGuess::Module;
132 } 136 }
133 } 137 }
134 } 138 }
diff --git a/crates/ide_db/src/helpers/insert_use/tests.rs b/crates/ide_db/src/helpers/insert_use/tests.rs
index 78a2a87b3..70b11bf81 100644
--- a/crates/ide_db/src/helpers/insert_use/tests.rs
+++ b/crates/ide_db/src/helpers/insert_use/tests.rs
@@ -663,6 +663,13 @@ use foo::bar::qux;
663", 663",
664 ImportGranularityGuess::Item, 664 ImportGranularityGuess::Item,
665 ); 665 );
666 check_guess(
667 r"
668use foo::bar::Bar;
669use foo::baz;
670",
671 ImportGranularityGuess::Item,
672 );
666} 673}
667 674
668#[test] 675#[test]
@@ -682,6 +689,14 @@ use foo::{baz::{qux, quux}, bar};
682", 689",
683 ImportGranularityGuess::Module, 690 ImportGranularityGuess::Module,
684 ); 691 );
692 check_guess(
693 r"
694use foo::bar::Bar;
695use foo::baz::Baz;
696use foo::{Foo, Qux};
697",
698 ImportGranularityGuess::Module,
699 );
685} 700}
686 701
687#[test] 702#[test]
diff --git a/crates/ide_db/src/helpers/merge_imports.rs b/crates/ide_db/src/helpers/merge_imports.rs
index 0dbabb44f..ec29476a4 100644
--- a/crates/ide_db/src/helpers/merge_imports.rs
+++ b/crates/ide_db/src/helpers/merge_imports.rs
@@ -124,7 +124,7 @@ fn recursive_merge(
124 .map(|tree_list| tree_list.use_trees().any(tree_is_self)) 124 .map(|tree_list| tree_list.use_trees().any(tree_is_self))
125 .unwrap_or(false) 125 .unwrap_or(false)
126 }; 126 };
127 match (tree_contains_self(&lhs_t), tree_contains_self(&rhs_t)) { 127 match (tree_contains_self(lhs_t), tree_contains_self(&rhs_t)) {
128 (true, false) => continue, 128 (true, false) => continue,
129 (false, true) => { 129 (false, true) => {
130 *lhs_t = rhs_t; 130 *lhs_t = rhs_t;
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs
index 1f900aef4..105607dca 100644
--- a/crates/ide_db/src/lib.rs
+++ b/crates/ide_db/src/lib.rs
@@ -93,6 +93,7 @@ impl RootDatabase {
93 db.set_crate_graph_with_durability(Default::default(), Durability::HIGH); 93 db.set_crate_graph_with_durability(Default::default(), Durability::HIGH);
94 db.set_local_roots_with_durability(Default::default(), Durability::HIGH); 94 db.set_local_roots_with_durability(Default::default(), Durability::HIGH);
95 db.set_library_roots_with_durability(Default::default(), Durability::HIGH); 95 db.set_library_roots_with_durability(Default::default(), Durability::HIGH);
96 db.set_enable_proc_attr_macros(Default::default());
96 db.update_lru_capacity(lru_capacity); 97 db.update_lru_capacity(lru_capacity);
97 db 98 db
98 } 99 }
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index 67840602b..a840e06a6 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -8,7 +8,8 @@ use std::{convert::TryInto, mem};
8 8
9use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; 9use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
10use hir::{ 10use hir::{
11 DefWithBody, HasAttrs, HasSource, InFile, ModuleDef, ModuleSource, Semantics, Visibility, 11 AsAssocItem, DefWithBody, HasAttrs, HasSource, InFile, ModuleDef, ModuleSource, Semantics,
12 Visibility,
12}; 13};
13use once_cell::unsync::Lazy; 14use once_cell::unsync::Lazy;
14use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
@@ -303,13 +304,13 @@ impl Definition {
303 } 304 }
304 } 305 }
305 306
306 pub fn usages<'a>(&'a self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> { 307 pub fn usages<'a>(self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> {
307 FindUsages { def: self, sema, scope: None, include_self_kw_refs: None } 308 FindUsages { def: self, sema, scope: None, include_self_kw_refs: None }
308 } 309 }
309} 310}
310 311
311pub struct FindUsages<'a> { 312pub struct FindUsages<'a> {
312 def: &'a Definition, 313 def: Definition,
313 sema: &'a Semantics<'a, RootDatabase>, 314 sema: &'a Semantics<'a, RootDatabase>,
314 scope: Option<SearchScope>, 315 scope: Option<SearchScope>,
315 include_self_kw_refs: Option<hir::Type>, 316 include_self_kw_refs: Option<hir::Type>,
@@ -318,7 +319,7 @@ pub struct FindUsages<'a> {
318impl<'a> FindUsages<'a> { 319impl<'a> FindUsages<'a> {
319 /// Enable searching for `Self` when the definition is a type. 320 /// Enable searching for `Self` when the definition is a type.
320 pub fn include_self_refs(mut self) -> FindUsages<'a> { 321 pub fn include_self_refs(mut self) -> FindUsages<'a> {
321 self.include_self_kw_refs = def_to_ty(self.sema, self.def); 322 self.include_self_kw_refs = def_to_ty(self.sema, &self.def);
322 self 323 self
323 } 324 }
324 325
@@ -408,7 +409,7 @@ impl<'a> FindUsages<'a> {
408 if let Some(ast::NameLike::NameRef(name_ref)) = 409 if let Some(ast::NameLike::NameRef(name_ref)) =
409 sema.find_node_at_offset_with_descend(&tree, offset) 410 sema.find_node_at_offset_with_descend(&tree, offset)
410 { 411 {
411 if self.found_self_ty_name_ref(&self_ty, &name_ref, sink) { 412 if self.found_self_ty_name_ref(self_ty, &name_ref, sink) {
412 return; 413 return;
413 } 414 }
414 } 415 }
@@ -423,7 +424,7 @@ impl<'a> FindUsages<'a> {
423 name_ref: &ast::NameRef, 424 name_ref: &ast::NameRef,
424 sink: &mut dyn FnMut(FileId, FileReference) -> bool, 425 sink: &mut dyn FnMut(FileId, FileReference) -> bool,
425 ) -> bool { 426 ) -> bool {
426 match NameRefClass::classify(self.sema, &name_ref) { 427 match NameRefClass::classify(self.sema, name_ref) {
427 Some(NameRefClass::Definition(Definition::SelfType(impl_))) 428 Some(NameRefClass::Definition(Definition::SelfType(impl_)))
428 if impl_.self_ty(self.sema.db) == *self_ty => 429 if impl_.self_ty(self.sema.db) == *self_ty =>
429 { 430 {
@@ -445,7 +446,7 @@ impl<'a> FindUsages<'a> {
445 sink: &mut dyn FnMut(FileId, FileReference) -> bool, 446 sink: &mut dyn FnMut(FileId, FileReference) -> bool,
446 ) -> bool { 447 ) -> bool {
447 match NameRefClass::classify_lifetime(self.sema, lifetime) { 448 match NameRefClass::classify_lifetime(self.sema, lifetime) {
448 Some(NameRefClass::Definition(def)) if &def == self.def => { 449 Some(NameRefClass::Definition(def)) if def == self.def => {
449 let FileRange { file_id, range } = self.sema.original_range(lifetime.syntax()); 450 let FileRange { file_id, range } = self.sema.original_range(lifetime.syntax());
450 let reference = FileReference { 451 let reference = FileReference {
451 range, 452 range,
@@ -463,13 +464,13 @@ impl<'a> FindUsages<'a> {
463 name_ref: &ast::NameRef, 464 name_ref: &ast::NameRef,
464 sink: &mut dyn FnMut(FileId, FileReference) -> bool, 465 sink: &mut dyn FnMut(FileId, FileReference) -> bool,
465 ) -> bool { 466 ) -> bool {
466 match NameRefClass::classify(self.sema, &name_ref) { 467 match NameRefClass::classify(self.sema, name_ref) {
467 Some(NameRefClass::Definition(def)) if &def == self.def => { 468 Some(NameRefClass::Definition(def)) if def == self.def => {
468 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); 469 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
469 let reference = FileReference { 470 let reference = FileReference {
470 range, 471 range,
471 name: ast::NameLike::NameRef(name_ref.clone()), 472 name: ast::NameLike::NameRef(name_ref.clone()),
472 access: reference_access(&def, &name_ref), 473 access: reference_access(&def, name_ref),
473 }; 474 };
474 sink(file_id, reference) 475 sink(file_id, reference)
475 } 476 }
@@ -479,7 +480,7 @@ impl<'a> FindUsages<'a> {
479 let reference = FileReference { 480 let reference = FileReference {
480 range, 481 range,
481 name: ast::NameLike::NameRef(name_ref.clone()), 482 name: ast::NameLike::NameRef(name_ref.clone()),
482 access: reference_access(&def, &name_ref), 483 access: reference_access(&def, name_ref),
483 }; 484 };
484 sink(file_id, reference) 485 sink(file_id, reference)
485 } else { 486 } else {
@@ -489,11 +490,9 @@ impl<'a> FindUsages<'a> {
489 Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => { 490 Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => {
490 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); 491 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
491 let access = match self.def { 492 let access = match self.def {
492 Definition::Field(_) if &field == self.def => { 493 Definition::Field(_) if field == self.def => reference_access(&field, name_ref),
493 reference_access(&field, &name_ref) 494 Definition::Local(l) if local == l => {
494 } 495 reference_access(&Definition::Local(local), name_ref)
495 Definition::Local(l) if &local == l => {
496 reference_access(&Definition::Local(local), &name_ref)
497 } 496 }
498 _ => return false, 497 _ => return false,
499 }; 498 };
@@ -513,7 +512,7 @@ impl<'a> FindUsages<'a> {
513 match NameClass::classify(self.sema, name) { 512 match NameClass::classify(self.sema, name) {
514 Some(NameClass::PatFieldShorthand { local_def: _, field_ref }) 513 Some(NameClass::PatFieldShorthand { local_def: _, field_ref })
515 if matches!( 514 if matches!(
516 self.def, Definition::Field(_) if &field_ref == self.def 515 self.def, Definition::Field(_) if field_ref == self.def
517 ) => 516 ) =>
518 { 517 {
519 let FileRange { file_id, range } = self.sema.original_range(name.syntax()); 518 let FileRange { file_id, range } = self.sema.original_range(name.syntax());
@@ -525,12 +524,38 @@ impl<'a> FindUsages<'a> {
525 }; 524 };
526 sink(file_id, reference) 525 sink(file_id, reference)
527 } 526 }
528 Some(NameClass::ConstReference(def)) if *self.def == def => { 527 Some(NameClass::ConstReference(def)) if self.def == def => {
529 let FileRange { file_id, range } = self.sema.original_range(name.syntax()); 528 let FileRange { file_id, range } = self.sema.original_range(name.syntax());
530 let reference = 529 let reference =
531 FileReference { range, name: ast::NameLike::Name(name.clone()), access: None }; 530 FileReference { range, name: ast::NameLike::Name(name.clone()), access: None };
532 sink(file_id, reference) 531 sink(file_id, reference)
533 } 532 }
533 // Resolve trait impl function definitions to the trait definition's version if self.def is the trait definition's
534 Some(NameClass::Definition(Definition::ModuleDef(mod_def))) => {
535 /* poor man's try block */
536 (|| {
537 let this = match self.def {
538 Definition::ModuleDef(this) if this != mod_def => this,
539 _ => return None,
540 };
541 let this_trait = this
542 .as_assoc_item(self.sema.db)?
543 .containing_trait_or_trait_impl(self.sema.db)?;
544 let trait_ = mod_def
545 .as_assoc_item(self.sema.db)?
546 .containing_trait_or_trait_impl(self.sema.db)?;
547 (trait_ == this_trait).then(|| {
548 let FileRange { file_id, range } = self.sema.original_range(name.syntax());
549 let reference = FileReference {
550 range,
551 name: ast::NameLike::Name(name.clone()),
552 access: None,
553 };
554 sink(file_id, reference)
555 })
556 })()
557 .unwrap_or(false)
558 }
534 _ => false, 559 _ => false,
535 } 560 }
536 } 561 }
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs
index 5c372a7e5..000f87a85 100644
--- a/crates/ide_db/src/symbol_index.rs
+++ b/crates/ide_db/src/symbol_index.rs
@@ -197,6 +197,7 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
197} 197}
198 198
199pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<FileSymbol> { 199pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<FileSymbol> {
200 let _p = profile::span("crate_symbols").detail(|| format!("{:?}", query));
200 // FIXME(#4842): This now depends on CrateDefMap, why not build the entire symbol index from 201 // FIXME(#4842): This now depends on CrateDefMap, why not build the entire symbol index from
201 // that instead? 202 // that instead?
202 203
@@ -321,6 +322,7 @@ impl SymbolIndex {
321 322
322impl Query { 323impl Query {
323 pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> { 324 pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> {
325 let _p = profile::span("symbol_index::Query::search");
324 let mut op = fst::map::OpBuilder::new(); 326 let mut op = fst::map::OpBuilder::new();
325 for file_symbols in indices.iter() { 327 for file_symbols in indices.iter() {
326 let automaton = fst::automaton::Subsequence::new(&self.lowercased); 328 let automaton = fst::automaton::Subsequence::new(&self.lowercased);