Description
To reproduce
pub trait Trait {}
pub fn test() {
struct Local;
impl Trait for Option<Local> {}
}
Compile with Beta ("Build using the Beta version: 1.79.0-beta.4 (2024-05-10 a269819)")
Expected results
I expected this to compile without warning.
Actual results
warning: non-local `impl` definition, they should be avoided as they go against expectation
--> src/lib.rs:6:5
|
6 | impl Trait for Option<Local> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: move this `impl` block outside the of the current function `test`
= note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl`
= note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
= note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
= note: `#[warn(non_local_definitions)]` on by default
Analysis
This is the new lint from RFC3373 (tracking issue).
In this code, the trait implementation cannot be moved out of the function, because it relies on types that are local to the function. The impl is coherence-legal only because the trait is within the same crate (so, this function couldn't be written outside Trait
's crate), since by coherence rules it's an impl on Option
. But the impl is reasonable where it is because its effects are invisible outside the function - no-one outside this function can see Local
, so they can't see Option<Local>
either - so they can't be affected by the impl.
In principle, the types could be moved too. But this will usually be undesirable. The compiler definitely ought not to be suggesting the programmer needlessly expose private items, just to satisfy this lint. (Also moving the types might involve renaming them.)
ISTM that this demonstrates that the rules for this lint need to be considerably more complicated than they are.
@rustbot label +regression-from-stable-to-beta