Skip to content
Merged
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions text/3373-avoid-nonlocal-definitions-in-fns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
- Feature Name: N/A
- Start Date: 2022-01-19
- RFC PR: [rust-lang/rfcs#3373](https://github.com/rust-lang/rfcs/pull/3373)
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)

# Summary
[summary]: #summary

Starting in Rust 2024, stop allowing items inside functions or expressions to
implement methods or traits that are visible outside the function or
expression.

# 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.

With this change, both humans and tools can limit the scope of their search and
avoid looking for definitions inside other functions or items, without missing
any relevant definitions.

# Explanation
Comment thread
joshtriplett marked this conversation as resolved.
[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`/`const` items
Comment thread
joshtriplett marked this conversation as resolved.
Outdated
Comment thread
joshtriplett marked this conversation as resolved.
Outdated
- The discriminant values assigned to `enum` variants

Starting in the Rust 2024 edition:
- 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.
Comment thread
joshtriplett marked this conversation as resolved.
- 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]`).
Comment thread
joshtriplett marked this conversation as resolved.

Rust 2015, 2018, and 2021 continue to permit this, but will produce a
Comment thread
joshtriplett marked this conversation as resolved.
Outdated
warn-by-default lint.

# 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.

Comment thread
joshtriplett marked this conversation as resolved.
# Unresolved questions
[unresolved-questions]: #unresolved-questions

We'll need a crater run to look at how widespread this pattern is in existing
code.

# 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.