|
| 1 | +- Feature Name: N/A |
| 2 | +- Start Date: 2022-01-19 |
| 3 | +- RFC PR: [rust-lang/rfcs#3373](https://github.com/rust-lang/rfcs/pull/3373) |
| 4 | +- Tracking Issue: [rust-lang/rust#120363](https://github.com/rust-lang/rust/issues/120363) |
| 5 | + |
| 6 | +# Summary |
| 7 | +[summary]: #summary |
| 8 | + |
| 9 | +Add a warn-by-default lint for items inside functions or expressions that |
| 10 | +implement methods or traits that are visible outside the function or |
| 11 | +expression. Consider ramping that lint to deny-by-default for Rust 2024, and |
| 12 | +evaluating a hard error for 2027. |
| 13 | + |
| 14 | +# Motivation |
| 15 | +[motivation]: #motivation |
| 16 | + |
| 17 | +Currently, tools cross-referencing uses and definitions (such as IDEs) must |
| 18 | +either search inside all function bodies and other expression-containing items |
| 19 | +to find potential definitions corresponding to uses within another function, or |
| 20 | +not cross-reference those definitions at all. |
| 21 | + |
| 22 | +Humans cross-referencing such uses and definitions may find themselves |
| 23 | +similarly baffled. |
| 24 | + |
| 25 | +This change helps humans limit the scope of their search and avoid looking for |
| 26 | +definitions inside other functions or items, without missing any relevant |
| 27 | +definitions. If in the future we manage to forbid it entirely within a |
| 28 | +subsequent Rust edtion, tools will be able to rely on this as well. |
| 29 | + |
| 30 | +# Explanation |
| 31 | +[explanation]: #explanation |
| 32 | + |
| 33 | +The following types of items, "expression-containing items", can contain |
| 34 | +expressions, including the definitions of other items: |
| 35 | +- Functions |
| 36 | +- Closures |
| 37 | +- The values assigned to `static` items or non-anonymous `const` items. |
| 38 | +- The discriminant values assigned to `enum` variants |
| 39 | + |
| 40 | +Rust will emit a warn-by-default lint for all of the following cases: |
| 41 | +- An item nested inside an expression-containing item (through any level of |
| 42 | + nesting) may not define an `impl Type` block unless the `Type` is also nested |
| 43 | + inside the same expression-containing item. |
| 44 | +- An item nested inside an expression-containing item (through any level of |
| 45 | + nesting) may not define an `impl Trait for Type` unless either the `Trait` or |
| 46 | + the `Type` is also nested inside the same expression-containing item. |
| 47 | +- An item nested inside an expression-containing item (through any level of |
| 48 | + nesting) may not define an exported macro visible outside the |
| 49 | + expression-containing item (e.g. using `#[macro_export]`). |
| 50 | + |
| 51 | +In a future edition, we may consider making this lint deny-by-default, or |
| 52 | +eventually making it a hard error. We'll evaluate the impact on the ecosystem |
| 53 | +and existing use cases before doing so. |
| 54 | + |
| 55 | +The lint is considered to attach to the `impl` token of an `impl` block, or the |
| 56 | +`macro_rules!` token of a macro definition. |
| 57 | + |
| 58 | +# Drawbacks |
| 59 | +[drawbacks]: #drawbacks |
| 60 | + |
| 61 | +Some existing code makes use of this pattern, and would need to migrate to a |
| 62 | +different pattern. In particular, this pattern may occur in macro-generated |
| 63 | +code, or in code generated by tools like rustdoc. Making this change would |
| 64 | +require such code and tools to restructure to meet this requirement. |
| 65 | + |
| 66 | +# Prior art |
| 67 | +[prior-art]: #prior-art |
| 68 | + |
| 69 | +Other aspects of Rust's design attempt to enable local reasoning and avoid |
| 70 | +global reasoning, including non-inference of function signatures, and not |
| 71 | +having the function body affect non-opaque properties of `impl Trait` uses in |
| 72 | +the signature without reflecting those properties in the signature. |
| 73 | + |
| 74 | +# Unresolved questions |
| 75 | +[unresolved-questions]: #unresolved-questions |
| 76 | + |
| 77 | +We'll need a crater run to look at how widespread this pattern is in existing |
| 78 | +code. |
| 79 | + |
| 80 | +Should we flag these definitions in anonymous `const` items as well, or would |
| 81 | +that produce unwanted warnings? |
| 82 | + |
| 83 | +# Future possibilities |
| 84 | +[future-possibilities]: #future-possibilities |
| 85 | + |
| 86 | +If in the future Rust provides a "standalone `derive`" mechanism (e.g. `derive |
| 87 | +Trait for Type` as a standalone definition separate from `Type`), the `impl` |
| 88 | +produced by that mechanism would be subject to the same requirements. |
0 commit comments