mirror of https://github.com/rust-lang/rfcs
Merge RFC 3373: Avoid non-local definitions in fns
The FCP for RFC 3373 completed on 2024-01-20 with a disposition to merge. Let's merge it.
This commit is contained in:
commit
0b566e818e
|
@ -0,0 +1,88 @@
|
|||
- Feature Name: N/A
|
||||
- Start Date: 2022-01-19
|
||||
- RFC PR: [rust-lang/rfcs#3373](https://github.com/rust-lang/rfcs/pull/3373)
|
||||
- Tracking Issue: [rust-lang/rust#120363](https://github.com/rust-lang/rust/issues/120363)
|
||||
|
||||
# Summary
|
||||
[summary]: #summary
|
||||
|
||||
Add a warn-by-default lint for items inside functions or expressions that
|
||||
implement methods or traits that are visible outside the function or
|
||||
expression. Consider ramping that lint to deny-by-default for Rust 2024, and
|
||||
evaluating a hard error for 2027.
|
||||
|
||||
# Motivation
|
||||
[motivation]: #motivation
|
||||
|
||||
Currently, tools cross-referencing uses and definitions (such as IDEs) must
|
||||
either search inside all function bodies and other expression-containing items
|
||||
to find potential definitions corresponding to uses within another function, or
|
||||
not cross-reference those definitions at all.
|
||||
|
||||
Humans cross-referencing such uses and definitions may find themselves
|
||||
similarly baffled.
|
||||
|
||||
This change helps humans limit the scope of their search and avoid looking for
|
||||
definitions inside other functions or items, without missing any relevant
|
||||
definitions. If in the future we manage to forbid it entirely within a
|
||||
subsequent Rust edtion, tools will be able to rely on this as well.
|
||||
|
||||
# Explanation
|
||||
[explanation]: #explanation
|
||||
|
||||
The following types of items, "expression-containing items", can contain
|
||||
expressions, including the definitions of other items:
|
||||
- Functions
|
||||
- Closures
|
||||
- The values assigned to `static` items or non-anonymous `const` items.
|
||||
- The discriminant values assigned to `enum` variants
|
||||
|
||||
Rust will emit a warn-by-default lint for all of the following cases:
|
||||
- An item nested inside an expression-containing item (through any level of
|
||||
nesting) may not define an `impl Type` block unless the `Type` is also nested
|
||||
inside the same expression-containing item.
|
||||
- An item nested inside an expression-containing item (through any level of
|
||||
nesting) may not define an `impl Trait for Type` unless either the `Trait` or
|
||||
the `Type` is also nested inside the same expression-containing item.
|
||||
- An item nested inside an expression-containing item (through any level of
|
||||
nesting) may not define an exported macro visible outside the
|
||||
expression-containing item (e.g. using `#[macro_export]`).
|
||||
|
||||
In a future edition, we may consider making this lint deny-by-default, or
|
||||
eventually making it a hard error. We'll evaluate the impact on the ecosystem
|
||||
and existing use cases before doing so.
|
||||
|
||||
The lint is considered to attach to the `impl` token of an `impl` block, or the
|
||||
`macro_rules!` token of a macro definition.
|
||||
|
||||
# Drawbacks
|
||||
[drawbacks]: #drawbacks
|
||||
|
||||
Some existing code makes use of this pattern, and would need to migrate to a
|
||||
different pattern. In particular, this pattern may occur in macro-generated
|
||||
code, or in code generated by tools like rustdoc. Making this change would
|
||||
require such code and tools to restructure to meet this requirement.
|
||||
|
||||
# Prior art
|
||||
[prior-art]: #prior-art
|
||||
|
||||
Other aspects of Rust's design attempt to enable local reasoning and avoid
|
||||
global reasoning, including non-inference of function signatures, and not
|
||||
having the function body affect non-opaque properties of `impl Trait` uses in
|
||||
the signature without reflecting those properties in the signature.
|
||||
|
||||
# Unresolved questions
|
||||
[unresolved-questions]: #unresolved-questions
|
||||
|
||||
We'll need a crater run to look at how widespread this pattern is in existing
|
||||
code.
|
||||
|
||||
Should we flag these definitions in anonymous `const` items as well, or would
|
||||
that produce unwanted warnings?
|
||||
|
||||
# Future possibilities
|
||||
[future-possibilities]: #future-possibilities
|
||||
|
||||
If in the future Rust provides a "standalone `derive`" mechanism (e.g. `derive
|
||||
Trait for Type` as a standalone definition separate from `Type`), the `impl`
|
||||
produced by that mechanism would be subject to the same requirements.
|
Loading…
Reference in New Issue