Skip to content

Commit 1e07c18

Browse files
committed
Point to the Self type and Trait to give for context
1 parent fe8f164 commit 1e07c18

15 files changed

+311
-69
lines changed

Diff for: Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4228,6 +4228,7 @@ dependencies = [
42284228
"rustc_feature",
42294229
"rustc_fluent_macro",
42304230
"rustc_hir",
4231+
"rustc_hir_pretty",
42314232
"rustc_index",
42324233
"rustc_infer",
42334234
"rustc_macros",

Diff for: compiler/rustc_lint/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ rustc_errors = { path = "../rustc_errors" }
1313
rustc_feature = { path = "../rustc_feature" }
1414
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
1515
rustc_hir = { path = "../rustc_hir" }
16+
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
1617
rustc_index = { path = "../rustc_index" }
1718
rustc_infer = { path = "../rustc_infer" }
1819
rustc_macros = { path = "../rustc_macros" }

Diff for: compiler/rustc_lint/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,10 @@ lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `#
476476
477477
lint_non_local_definitions_may_move = may need to be moved as well
478478
479+
lint_non_local_definitions_of_trait_not_local = `{$of_trait_str}` is not local
480+
481+
lint_non_local_definitions_self_ty_not_local = `{$self_ty_str}` is not local
482+
479483
lint_non_snake_case = {$sort} `{$name}` should have a snake case name
480484
.rename_or_convert_suggestion = rename the identifier or convert it to a snake case raw identifier
481485
.cannot_convert_note = `{$sc}` cannot be used as a raw identifier

Diff for: compiler/rustc_lint/src/lints.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,8 @@ pub enum NonLocalDefinitionsDiag {
13441344
may_move: Vec<Span>,
13451345
may_remove: Option<(Span, String)>,
13461346
has_trait: bool,
1347+
self_ty_str: String,
1348+
of_trait_str: Option<String>,
13471349
},
13481350
MacroRules {
13491351
depth: u32,
@@ -1368,10 +1370,16 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
13681370
may_move,
13691371
may_remove,
13701372
has_trait,
1373+
self_ty_str,
1374+
of_trait_str,
13711375
} => {
13721376
diag.arg("depth", depth);
13731377
diag.arg("body_kind_descr", body_kind_descr);
13741378
diag.arg("body_name", body_name);
1379+
diag.arg("self_ty_str", self_ty_str);
1380+
if let Some(of_trait_str) = of_trait_str {
1381+
diag.arg("of_trait_str", of_trait_str);
1382+
}
13751383

13761384
if has_trait {
13771385
diag.note(fluent::lint_bounds);

Diff for: compiler/rustc_lint/src/non_local_def.rs

+76-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_errors::MultiSpan;
12
use rustc_hir::intravisit::{self, Visitor};
23
use rustc_hir::HirId;
34
use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, TyKind};
@@ -9,12 +10,13 @@ use rustc_middle::ty::{EarlyBinder, TraitRef, TypeSuperFoldable};
910
use rustc_session::{declare_lint, impl_lint_pass};
1011
use rustc_span::def_id::{DefId, LOCAL_CRATE};
1112
use rustc_span::Span;
12-
use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind};
13+
use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind, Symbol};
1314
use rustc_trait_selection::infer::TyCtxtInferExt;
1415
use rustc_trait_selection::traits::error_reporting::ambiguity::{
1516
compute_applicable_impls_for_diagnostics, CandidateSource,
1617
};
1718

19+
use crate::fluent_generated as fluent;
1820
use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag};
1921
use crate::{LateContext, LateLintPass, LintContext};
2022

@@ -201,11 +203,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
201203
.into_iter()
202204
.filter_map(|path| {
203205
if path_has_local_parent(&path, cx, parent, parent_parent) {
204-
if let Some(args) = &path.segments.last().unwrap().args {
205-
Some(path.span.until(args.span_ext))
206-
} else {
207-
Some(path.span)
208-
}
206+
Some(path_span_without_args(&path))
209207
} else {
210208
None
211209
}
@@ -227,9 +225,29 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
227225
_ => None,
228226
};
229227

228+
let impl_span = item.span.shrink_to_lo().to(impl_.self_ty.span);
229+
let mut ms = MultiSpan::from_span(impl_span);
230+
231+
let (self_ty_span, self_ty_str) =
232+
self_ty_kind_for_diagnostic(&impl_.self_ty, cx.tcx);
233+
234+
ms.push_span_label(
235+
self_ty_span,
236+
fluent::lint_non_local_definitions_self_ty_not_local,
237+
);
238+
let of_trait_str = if let Some(of_trait) = &impl_.of_trait {
239+
ms.push_span_label(
240+
path_span_without_args(&of_trait.path),
241+
fluent::lint_non_local_definitions_of_trait_not_local,
242+
);
243+
Some(path_name_to_string(&of_trait.path))
244+
} else {
245+
None
246+
};
247+
230248
cx.emit_span_lint(
231249
NON_LOCAL_DEFINITIONS,
232-
item.span.shrink_to_lo().to(impl_.self_ty.span),
250+
ms,
233251
NonLocalDefinitionsDiag::Impl {
234252
depth: self.body_depth,
235253
move_help: item.span,
@@ -239,6 +257,8 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
239257
.unwrap_or_else(|| "<unnameable>".to_string()),
240258
cargo_update: cargo_update(),
241259
const_anon,
260+
self_ty_str,
261+
of_trait_str,
242262
may_move,
243263
may_remove,
244264
has_trait: impl_.of_trait.is_some(),
@@ -447,3 +467,52 @@ fn did_has_local_parent(
447467
false
448468
}
449469
}
470+
471+
/// Return for a given `Path` the span until the last args
472+
fn path_span_without_args(path: &Path<'_>) -> Span {
473+
if let Some(args) = &path.segments.last().unwrap().args {
474+
path.span.until(args.span_ext)
475+
} else {
476+
path.span
477+
}
478+
}
479+
480+
/// Return a "error message-able" ident for the last segment of the `Path`
481+
fn path_name_to_string(path: &Path<'_>) -> String {
482+
path.segments.last().unwrap().ident.name.to_ident_string()
483+
}
484+
485+
/// Compute the `Span` and visual representation for the `Self` we want to point at;
486+
/// It follows part of the actual logic of non-local, and if possible return the least
487+
/// amount possible for the span and representation.
488+
fn self_ty_kind_for_diagnostic(ty: &rustc_hir::Ty<'_>, tcx: TyCtxt<'_>) -> (Span, String) {
489+
match ty.kind {
490+
TyKind::Path(QPath::Resolved(_, ty_path)) => (
491+
path_span_without_args(ty_path),
492+
ty_path
493+
.res
494+
.opt_def_id()
495+
.map(|did| tcx.opt_item_name(did))
496+
.flatten()
497+
.as_ref()
498+
.map(|s| Symbol::as_str(s))
499+
.unwrap_or("<unnameable>")
500+
.to_string(),
501+
),
502+
TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => {
503+
let path = &principle_poly_trait_ref.trait_ref.path;
504+
(
505+
path_span_without_args(path),
506+
path.res
507+
.opt_def_id()
508+
.map(|did| tcx.opt_item_name(did))
509+
.flatten()
510+
.as_ref()
511+
.map(|s| Symbol::as_str(s))
512+
.unwrap_or("<unnameable>")
513+
.to_string(),
514+
)
515+
}
516+
_ => (ty.span, rustc_hir_pretty::ty_to_string(&tcx, ty)),
517+
}
518+
}

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

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
33
|
44
LL | non_local_macro::non_local_impl!(LocalStruct);
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
| |
7+
| `LocalStruct` is not local
8+
| `Debug` is not local
69
|
710
= 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
811
= 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`

Diff for: tests/ui/lint/non-local-defs/consts.stderr

+29-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ LL | const Z: () = {
55
| - help: use a const-anon item to suppress this lint: `_`
66
...
77
LL | impl Uto for &Test {}
8-
| ^^^^^^^^^^^^^^^^^^
8+
| ^^^^^---^^^^^-----
9+
| | |
10+
| | `&'_ Test` is not local
11+
| `Uto` is not local
912
|
1013
= 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
1114
= 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`
@@ -22,7 +25,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
2225
--> $DIR/consts.rs:24:5
2326
|
2427
LL | impl Uto2 for Test {}
25-
| ^^^^^^^^^^^^^^^^^^
28+
| ^^^^^----^^^^^----
29+
| | |
30+
| | `Test` is not local
31+
| `Uto2` is not local
2632
|
2733
= 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
2834
= 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,7 +44,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
3844
--> $DIR/consts.rs:32:5
3945
|
4046
LL | impl Uto3 for Test {}
41-
| ^^^^^^^^^^^^^^^^^^
47+
| ^^^^^----^^^^^----
48+
| | |
49+
| | `Test` is not local
50+
| `Uto3` is not local
4251
|
4352
= 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
4453
= 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,7 +63,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
5463
--> $DIR/consts.rs:43:5
5564
|
5665
LL | impl Test {
57-
| ^^^^^^^^^
66+
| ^^^^^----
67+
| |
68+
| `Test` is not local
5869
|
5970
= 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`
6071
help: move this `impl` block outside of the current function `main`
@@ -71,7 +82,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
7182
--> $DIR/consts.rs:50:9
7283
|
7384
LL | impl Test {
74-
| ^^^^^^^^^
85+
| ^^^^^----
86+
| |
87+
| `Test` is not local
7588
|
7689
= 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`
7790
help: move this `impl` block outside of the current inline constant `<unnameable>` and up 2 bodies
@@ -88,7 +101,9 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
88101
--> $DIR/consts.rs:59:9
89102
|
90103
LL | impl Test {
91-
| ^^^^^^^^^
104+
| ^^^^^----
105+
| |
106+
| `Test` is not local
92107
|
93108
= 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`
94109
help: move this `impl` block outside of the current constant `_` and up 2 bodies
@@ -106,7 +121,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
106121
--> $DIR/consts.rs:72:9
107122
|
108123
LL | impl Uto9 for Test {}
109-
| ^^^^^^^^^^^^^^^^^^
124+
| ^^^^^----^^^^^----
125+
| | |
126+
| | `Test` is not local
127+
| `Uto9` is not local
110128
|
111129
= 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
112130
= 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`
@@ -121,7 +139,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
121139
--> $DIR/consts.rs:79:9
122140
|
123141
LL | impl Uto10 for Test {}
124-
| ^^^^^^^^^^^^^^^^^^^
142+
| ^^^^^-----^^^^^----
143+
| | |
144+
| | `Test` is not local
145+
| `Uto10` is not local
125146
|
126147
= 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
127148
= 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`

Diff for: tests/ui/lint/non-local-defs/exhaustive-trait.stderr

+24-6
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/exhaustive-trait.rs:7:5
33
|
44
LL | impl PartialEq<()> for Dog {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^---------^^^^^^^^^---
6+
| | |
7+
| | `Dog` is not local
8+
| `PartialEq` is not local
69
|
710
= 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
811
= 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`
@@ -23,7 +26,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
2326
--> $DIR/exhaustive-trait.rs:14:5
2427
|
2528
LL | impl PartialEq<()> for &Dog {
26-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
29+
| ^^^^^---------^^^^^^^^^----
30+
| | |
31+
| | `&'_ Dog` is not local
32+
| `PartialEq` is not local
2733
|
2834
= 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
2935
= 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`
@@ -43,7 +49,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
4349
--> $DIR/exhaustive-trait.rs:21:5
4450
|
4551
LL | impl PartialEq<Dog> for () {
46-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
52+
| ^^^^^---------^^^^^^^^^^--
53+
| | |
54+
| | `()` is not local
55+
| `PartialEq` is not local
4756
|
4857
= 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
4958
= 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`
@@ -63,7 +72,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
6372
--> $DIR/exhaustive-trait.rs:28:5
6473
|
6574
LL | impl PartialEq<&Dog> for () {
66-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
75+
| ^^^^^---------^^^^^^^^^^^--
76+
| | |
77+
| | `()` is not local
78+
| `PartialEq` is not local
6779
|
6880
= 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
6981
= 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`
@@ -83,7 +95,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
8395
--> $DIR/exhaustive-trait.rs:35:5
8496
|
8597
LL | impl PartialEq<Dog> for &Dog {
86-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
98+
| ^^^^^---------^^^^^^^^^^----
99+
| | |
100+
| | `&'_ Dog` is not local
101+
| `PartialEq` is not local
87102
|
88103
= 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
89104
= 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`
@@ -103,7 +118,10 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam
103118
--> $DIR/exhaustive-trait.rs:42:5
104119
|
105120
LL | impl PartialEq<&Dog> for &Dog {
106-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
121+
| ^^^^^---------^^^^^^^^^^^----
122+
| | |
123+
| | `&'_ Dog` is not local
124+
| `PartialEq` is not local
107125
|
108126
= 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
109127
= 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`

0 commit comments

Comments
 (0)