Skip to content

Commit 0b566e8

Browse files
committed
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.
2 parents 6a60069 + ba3d5f5 commit 0b566e8

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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

Comments
 (0)