Skip to content

Commit de1c122

Browse files
committed
non_local_defs: improve some notes around trait, bounds, consts
- Restrict const-anon exception diag to relevant places - Invoke bounds (and type-inference) in non_local_defs - Specialize diagnostic for impl without Trait
1 parent 06c6a2d commit de1c122

12 files changed

+141
-128
lines changed

compiler/rustc_lint/messages.ftl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,10 @@ lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks sho
548548
[one] `{$body_name}`
549549
*[other] `{$body_name}` and up {$depth} bodies
550550
}
551-
.non_local = 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`
552-
.exception = 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
551+
.without_trait = methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block
552+
.with_trait = an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
553+
.bounds = `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
554+
.exception = anon-const (`const _: () = {"{"} ... {"}"}`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level
553555
.const_anon = use a const-anon item to suppress this lint
554556
555557
lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module

compiler/rustc_lint/src/lints.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,7 +1335,8 @@ pub enum NonLocalDefinitionsDiag {
13351335
body_kind_descr: &'static str,
13361336
body_name: String,
13371337
cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
1338-
const_anon: Option<Span>,
1338+
const_anon: Option<Option<Span>>,
1339+
has_trait: bool,
13391340
},
13401341
MacroRules {
13411342
depth: u32,
@@ -1356,28 +1357,37 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
13561357
body_name,
13571358
cargo_update,
13581359
const_anon,
1360+
has_trait,
13591361
} => {
13601362
diag.primary_message(fluent::lint_non_local_definitions_impl);
13611363
diag.arg("depth", depth);
13621364
diag.arg("body_kind_descr", body_kind_descr);
13631365
diag.arg("body_name", body_name);
13641366

13651367
diag.help(fluent::lint_help);
1366-
diag.note(fluent::lint_non_local);
1367-
diag.note(fluent::lint_exception);
1368-
diag.note(fluent::lint_non_local_definitions_deprecation);
1368+
if has_trait {
1369+
diag.note(fluent::lint_bounds);
1370+
diag.note(fluent::lint_with_trait);
1371+
} else {
1372+
diag.note(fluent::lint_without_trait);
1373+
}
13691374

13701375
if let Some(cargo_update) = cargo_update {
13711376
diag.subdiagnostic(&diag.dcx, cargo_update);
13721377
}
13731378
if let Some(const_anon) = const_anon {
1374-
diag.span_suggestion(
1375-
const_anon,
1376-
fluent::lint_const_anon,
1377-
"_",
1378-
Applicability::MachineApplicable,
1379-
);
1379+
diag.note(fluent::lint_exception);
1380+
if let Some(const_anon) = const_anon {
1381+
diag.span_suggestion(
1382+
const_anon,
1383+
fluent::lint_const_anon,
1384+
"_",
1385+
Applicability::MachineApplicable,
1386+
);
1387+
}
13801388
}
1389+
1390+
diag.note(fluent::lint_non_local_definitions_deprecation);
13811391
}
13821392
NonLocalDefinitionsDiag::MacroRules {
13831393
depth,

compiler/rustc_lint/src/non_local_def.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
202202
// Get the span of the parent const item ident (if it's a not a const anon).
203203
//
204204
// Used to suggest changing the const item to a const anon.
205-
let span_for_const_anon_suggestion = if self.body_depth == 1
206-
&& parent_def_kind == DefKind::Const
205+
let span_for_const_anon_suggestion = if parent_def_kind == DefKind::Const
207206
&& parent_opt_item_name != Some(kw::Underscore)
208207
&& let Some(parent) = parent.as_local()
209208
&& let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent)
@@ -215,6 +214,9 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
215214
None
216215
};
217216

217+
let const_anon = matches!(parent_def_kind, DefKind::Const | DefKind::Static { .. })
218+
.then_some(span_for_const_anon_suggestion);
219+
218220
cx.emit_span_lint(
219221
NON_LOCAL_DEFINITIONS,
220222
item.span,
@@ -225,7 +227,8 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
225227
.map(|s| s.to_ident_string())
226228
.unwrap_or_else(|| "<unnameable>".to_string()),
227229
cargo_update: cargo_update(),
228-
const_anon: span_for_const_anon_suggestion,
230+
const_anon,
231+
has_trait: impl_.of_trait.is_some(),
229232
},
230233
)
231234
}

tests/ui/lint/non-local-defs/cargo-update.stderr

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ LL | non_local_macro::non_local_impl!(LocalStruct);
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= help: move this `impl` block outside the of the current constant `_IMPL_DEBUG`
8-
= 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`
9-
= 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
10-
= 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>
8+
= note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
9+
= note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
1110
= note: the macro `non_local_macro::non_local_impl` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro`
11+
= note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level
12+
= 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>
1213
= note: `#[warn(non_local_definitions)]` on by default
1314
= note: this warning originates in the macro `non_local_macro::non_local_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
1415

tests/ui/lint/non-local-defs/consts.stderr

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ LL | impl Uto for &Test {}
88
| ^^^^^^^^^^^^^^^^^^^^^
99
|
1010
= help: move this `impl` block outside the of the current constant `Z`
11-
= 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`
12-
= 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
11+
= note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
12+
= note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
13+
= note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level
1314
= 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>
1415
= note: `#[warn(non_local_definitions)]` on by default
1516

@@ -20,8 +21,9 @@ LL | impl Uto2 for Test {}
2021
| ^^^^^^^^^^^^^^^^^^^^^
2122
|
2223
= help: move this `impl` block outside the of the current static `A`
23-
= 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`
24-
= 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
24+
= note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
25+
= note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
26+
= note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level
2527
= 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>
2628

2729
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
@@ -31,8 +33,9 @@ LL | impl Uto3 for Test {}
3133
| ^^^^^^^^^^^^^^^^^^^^^
3234
|
3335
= help: move this `impl` block outside the of the current constant `B`
34-
= 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`
35-
= 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
36+
= note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
37+
= note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
38+
= note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level
3639
= 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>
3740

3841
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
@@ -45,8 +48,7 @@ LL | | }
4548
| |_____^
4649
|
4750
= help: move this `impl` block outside the of the current function `main`
48-
= 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`
49-
= 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
51+
= note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block
5052
= 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>
5153

5254
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
@@ -59,8 +61,7 @@ LL | | }
5961
| |_________^
6062
|
6163
= help: move this `impl` block outside the of the current inline constant `<unnameable>` and up 2 bodies
62-
= 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`
63-
= 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
64+
= note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block
6465
= 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>
6566

6667
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
@@ -73,8 +74,8 @@ LL | | }
7374
| |_________^
7475
|
7576
= help: move this `impl` block outside the of the current constant `_` and up 2 bodies
76-
= 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`
77-
= 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
77+
= note: methods and assoc const are still usable outside the current expression, only `impl Local` and `impl dyn Local` are local and only if the `Local` type is at the same nesting as the `impl` block
78+
= note: anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type are consider to be transparent regarding the nesting level
7879
= 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>
7980

8081
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
@@ -84,8 +85,8 @@ LL | impl Uto9 for Test {}
8485
| ^^^^^^^^^^^^^^^^^^^^^
8586
|
8687
= help: move this `impl` block outside the of the current closure `<unnameable>` and up 2 bodies
87-
= 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`
88-
= 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
88+
= note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
89+
= note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
8990
= 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>
9091

9192
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
@@ -95,8 +96,8 @@ LL | impl Uto10 for Test {}
9596
| ^^^^^^^^^^^^^^^^^^^^^^
9697
|
9798
= help: move this `impl` block outside the of the current constant expression `<unnameable>` and up 2 bodies
98-
= 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`
99-
= 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
99+
= note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
100+
= note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
100101
= 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>
101102

102103
warning: 8 warnings emitted

0 commit comments

Comments
 (0)