Skip to content

Commit 7236f18

Browse files
committed
Point the parent item and items that needs to be moved when appropriate
1 parent 10fcf87 commit 7236f18

13 files changed

+311
-462
lines changed

compiler/rustc_lint/messages.ftl

+6-5
Original file line numberDiff line numberDiff line change
@@ -543,18 +543,19 @@ lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may
543543
lint_non_local_definitions_deprecation = 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>
544544
545545
lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks should be written at the same level as their item
546-
.move_help =
547-
move this `impl` block outside of the current {$body_kind_descr} {$depth ->
548-
[one] `{$body_name}`
549-
*[other] `{$body_name}` and up {$depth} bodies
550-
}
551546
.remove_help = remove `{$may_remove_part}` to make the `impl` local
552547
.without_trait = methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl`
553548
.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`
554549
.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
555550
.exception = items in an anonymous const item (`const _: () = {"{"} ... {"}"}`) are treated as in the same scope as the anonymous const's declaration
556551
.const_anon = use a const-anon item to suppress this lint
557552
553+
lint_non_local_definitions_impl_move_help =
554+
move this `impl` block outside of the current {$body_kind_descr} {$depth ->
555+
[one] `{$body_name}`
556+
*[other] `{$body_name}` and up {$depth} bodies
557+
}
558+
558559
lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module
559560
.help =
560561
remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth ->

compiler/rustc_lint/src/lints.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -1347,8 +1347,7 @@ pub enum NonLocalDefinitionsDiag {
13471347
body_name: String,
13481348
cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
13491349
const_anon: Option<Option<Span>>,
1350-
move_help: Span,
1351-
may_move: Vec<Span>,
1350+
move_to: Option<(Span, Vec<Span>)>,
13521351
may_remove: Option<(Span, String)>,
13531352
has_trait: bool,
13541353
self_ty_str: String,
@@ -1373,8 +1372,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
13731372
body_name,
13741373
cargo_update,
13751374
const_anon,
1376-
move_help,
1377-
may_move,
1375+
move_to,
13781376
may_remove,
13791377
has_trait,
13801378
self_ty_str,
@@ -1395,11 +1393,13 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
13951393
diag.note(fluent::lint_without_trait);
13961394
}
13971395

1398-
let mut ms = MultiSpan::from_span(move_help);
1399-
for sp in may_move {
1400-
ms.push_span_label(sp, fluent::lint_non_local_definitions_may_move);
1396+
if let Some((move_help, may_move)) = move_to {
1397+
let mut ms = MultiSpan::from_span(move_help);
1398+
for sp in may_move {
1399+
ms.push_span_label(sp, fluent::lint_non_local_definitions_may_move);
1400+
}
1401+
diag.span_help(ms, fluent::lint_non_local_definitions_impl_move_help);
14011402
}
1402-
diag.span_help(ms, fluent::lint_move_help);
14031403

14041404
if let Some((span, part)) = may_remove {
14051405
diag.arg("may_remove_part", part);

compiler/rustc_lint/src/non_local_def.rs

+17-5
Original file line numberDiff line numberDiff line change
@@ -198,17 +198,21 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
198198
}
199199
collector.visit_generics(&impl_.generics);
200200

201-
let may_move: Vec<Span> = collector
201+
let mut may_move: Vec<Span> = collector
202202
.paths
203203
.into_iter()
204204
.filter_map(|path| {
205-
if path_has_local_parent(&path, cx, parent, parent_parent) {
206-
Some(path_span_without_args(&path))
205+
if let Some(did) = path.res.opt_def_id()
206+
&& did_has_local_parent(did, cx.tcx, parent, parent_parent)
207+
{
208+
Some(cx.tcx.def_span(did))
207209
} else {
208210
None
209211
}
210212
})
211213
.collect();
214+
may_move.sort();
215+
may_move.dedup();
212216

213217
let const_anon = matches!(parent_def_kind, DefKind::Const | DefKind::Static { .. })
214218
.then_some(span_for_const_anon_suggestion);
@@ -244,13 +248,21 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
244248
} else {
245249
None
246250
};
251+
let move_to = if may_move.is_empty() {
252+
ms.push_span_label(
253+
cx.tcx.def_span(parent),
254+
fluent::lint_non_local_definitions_impl_move_help,
255+
);
256+
None
257+
} else {
258+
Some((cx.tcx.def_span(parent), may_move))
259+
};
247260

248261
cx.emit_span_lint(
249262
NON_LOCAL_DEFINITIONS,
250263
ms,
251264
NonLocalDefinitionsDiag::Impl {
252265
depth: self.body_depth,
253-
move_help: item.span,
254266
body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind, parent),
255267
body_name: parent_opt_item_name
256268
.map(|s| s.to_ident_string())
@@ -259,7 +271,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
259271
const_anon,
260272
self_ty_str,
261273
of_trait_str,
262-
may_move,
274+
move_to,
263275
may_remove,
264276
has_trait: impl_.of_trait.is_some(),
265277
},

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

+1-5
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,10 @@ LL | non_local_macro::non_local_impl!(LocalStruct);
66
| |
77
| `LocalStruct` is not local
88
| `Debug` is not local
9+
| move this `impl` block outside of the current constant `_IMPL_DEBUG`
910
|
1011
= 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
1112
= 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`
12-
help: move this `impl` block outside of the current constant `_IMPL_DEBUG`
13-
--> $DIR/cargo-update.rs:17:1
14-
|
15-
LL | non_local_macro::non_local_impl!(LocalStruct);
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1713
= 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`
1814
= note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration
1915
= 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>

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

+37-59
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
22
--> $DIR/consts.rs:13:5
33
|
44
LL | const Z: () = {
5-
| - help: use a const-anon item to suppress this lint: `_`
5+
| -----------
6+
| | |
7+
| | help: use a const-anon item to suppress this lint: `_`
8+
| move this `impl` block outside of the current constant `Z`
69
...
710
LL | impl Uto for &Test {}
811
| ^^^^^---^^^^^-----
@@ -12,18 +15,15 @@ LL | impl Uto for &Test {}
1215
|
1316
= 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
1417
= 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`
15-
help: move this `impl` block outside of the current constant `Z`
16-
--> $DIR/consts.rs:13:5
17-
|
18-
LL | impl Uto for &Test {}
19-
| ^^^^^^^^^^^^^^^^^^^^^
2018
= note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration
2119
= 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>
2220
= note: `#[warn(non_local_definitions)]` on by default
2321

2422
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
2523
--> $DIR/consts.rs:24:5
2624
|
25+
LL | static A: u32 = {
26+
| ------------- move this `impl` block outside of the current static `A`
2727
LL | impl Uto2 for Test {}
2828
| ^^^^^----^^^^^----
2929
| | |
@@ -32,17 +32,14 @@ LL | impl Uto2 for Test {}
3232
|
3333
= 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
3434
= 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`
35-
help: move this `impl` block outside of the current static `A`
36-
--> $DIR/consts.rs:24:5
37-
|
38-
LL | impl Uto2 for Test {}
39-
| ^^^^^^^^^^^^^^^^^^^^^
4035
= note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration
4136
= 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>
4237

4338
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
4439
--> $DIR/consts.rs:32:5
4540
|
41+
LL | const B: u32 = {
42+
| ------------ move this `impl` block outside of the current constant `B`
4643
LL | impl Uto3 for Test {}
4744
| ^^^^^----^^^^^----
4845
| | |
@@ -51,75 +48,60 @@ LL | impl Uto3 for Test {}
5148
|
5249
= 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
5350
= 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`
54-
help: move this `impl` block outside of the current constant `B`
55-
--> $DIR/consts.rs:32:5
56-
|
57-
LL | impl Uto3 for Test {}
58-
| ^^^^^^^^^^^^^^^^^^^^^
5951
= note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration
6052
= 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>
6153

6254
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
6355
--> $DIR/consts.rs:43:5
6456
|
57+
LL | fn main() {
58+
| --------- move this `impl` block outside of the current function `main`
6559
LL | impl Test {
6660
| ^^^^^----
6761
| |
6862
| `Test` is not local
6963
|
7064
= note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl`
71-
help: move this `impl` block outside of the current function `main`
72-
--> $DIR/consts.rs:43:5
73-
|
74-
LL | / impl Test {
75-
LL | |
76-
LL | | fn foo() {}
77-
LL | | }
78-
| |_____^
7965
= 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>
8066

8167
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
8268
--> $DIR/consts.rs:50:9
8369
|
84-
LL | impl Test {
85-
| ^^^^^----
86-
| |
87-
| `Test` is not local
88-
|
89-
= note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl`
90-
help: move this `impl` block outside of the current inline constant `<unnameable>` and up 2 bodies
91-
--> $DIR/consts.rs:50:9
92-
|
93-
LL | / impl Test {
70+
LL | const {
71+
| ___________-
72+
LL | | impl Test {
73+
| | ^^^^^----
74+
| | |
75+
| | `Test` is not local
9476
LL | |
9577
LL | | fn hoo() {}
96-
LL | | }
97-
| |_________^
78+
... |
79+
LL | | 1
80+
LL | | };
81+
| |_____- move this `impl` block outside of the current inline constant `<unnameable>` and up 2 bodies
82+
|
83+
= note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl`
9884
= 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>
9985

10086
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
10187
--> $DIR/consts.rs:59:9
10288
|
89+
LL | const _: u32 = {
90+
| ------------ move this `impl` block outside of the current constant `_` and up 2 bodies
10391
LL | impl Test {
10492
| ^^^^^----
10593
| |
10694
| `Test` is not local
10795
|
10896
= note: methods and associated constants are still usable outside the current expression, only `impl Local` and `impl dyn Local` can ever be private, and only if the type is nested in the same item as the `impl`
109-
help: move this `impl` block outside of the current constant `_` and up 2 bodies
110-
--> $DIR/consts.rs:59:9
111-
|
112-
LL | / impl Test {
113-
LL | |
114-
LL | | fn foo2() {}
115-
LL | | }
116-
| |_________^
11797
= note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration
11898
= 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>
11999

120100
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
121101
--> $DIR/consts.rs:72:9
122102
|
103+
LL | let _a = || {
104+
| -- move this `impl` block outside of the current closure `<unnameable>` and up 2 bodies
123105
LL | impl Uto9 for Test {}
124106
| ^^^^^----^^^^^----
125107
| | |
@@ -128,29 +110,25 @@ LL | impl Uto9 for Test {}
128110
|
129111
= 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
130112
= 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`
131-
help: move this `impl` block outside of the current closure `<unnameable>` and up 2 bodies
132-
--> $DIR/consts.rs:72:9
133-
|
134-
LL | impl Uto9 for Test {}
135-
| ^^^^^^^^^^^^^^^^^^^^^
136113
= 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>
137114

138115
warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item
139116
--> $DIR/consts.rs:79:9
140117
|
141-
LL | impl Uto10 for Test {}
142-
| ^^^^^-----^^^^^----
143-
| | |
144-
| | `Test` is not local
145-
| `Uto10` is not local
118+
LL | type A = [u32; {
119+
| ____________________-
120+
LL | | impl Uto10 for Test {}
121+
| | ^^^^^-----^^^^^----
122+
| | | |
123+
| | | `Test` is not local
124+
| | `Uto10` is not local
125+
LL | |
126+
... |
127+
LL | | }];
128+
| |_____- move this `impl` block outside of the current constant expression `<unnameable>` and up 2 bodies
146129
|
147130
= 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
148131
= 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`
149-
help: move this `impl` block outside of the current constant expression `<unnameable>` and up 2 bodies
150-
--> $DIR/consts.rs:79:9
151-
|
152-
LL | impl Uto10 for Test {}
153-
| ^^^^^^^^^^^^^^^^^^^^^^
154132
= 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>
155133

156134
warning: 8 warnings emitted

0 commit comments

Comments
 (0)