Skip to content

Commit 224ad32

Browse files
committed
Account for enclosing item when suggesting new lifetime name
1 parent 8f7ee34 commit 224ad32

File tree

5 files changed

+96
-23
lines changed

5 files changed

+96
-23
lines changed

src/librustc_infer/infer/error_reporting/mod.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use rustc_errors::{pluralize, struct_span_err};
6060
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
6161
use rustc_hir as hir;
6262
use rustc_hir::def_id::DefId;
63-
use rustc_hir::Node;
63+
use rustc_hir::{Item, ItemKind, Node};
6464
use rustc_middle::ty::error::TypeError;
6565
use rustc_middle::ty::{
6666
self,
@@ -1685,12 +1685,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16851685
let hir = &self.tcx.hir();
16861686
// Attempt to obtain the span of the parameter so we can
16871687
// suggest adding an explicit lifetime bound to it.
1688-
let generics = self
1689-
.in_progress_tables
1690-
.and_then(|table| table.borrow().hir_owner)
1691-
.map(|table_owner| self.tcx.generics_of(table_owner.to_def_id()));
1688+
let generics =
1689+
self.in_progress_tables.and_then(|table| table.borrow().hir_owner).map(|table_owner| {
1690+
let hir_id = hir.as_local_hir_id(table_owner);
1691+
let parent_id = hir.get_parent_item(hir_id);
1692+
(
1693+
// Parent item could be a `mod`, so we check the HIR before calling:
1694+
if let Some(Node::Item(Item {
1695+
kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
1696+
..
1697+
})) = hir.find(parent_id)
1698+
{
1699+
Some(self.tcx.generics_of(hir.local_def_id(parent_id).to_def_id()))
1700+
} else {
1701+
None
1702+
},
1703+
self.tcx.generics_of(table_owner.to_def_id()),
1704+
)
1705+
});
16921706
let type_param_span = match (generics, bound_kind) {
1693-
(Some(ref generics), GenericKind::Param(ref param)) => {
1707+
(Some((_, ref generics)), GenericKind::Param(ref param)) => {
16941708
// Account for the case where `param` corresponds to `Self`,
16951709
// which doesn't have the expected type argument.
16961710
if !(generics.has_self && param.index == 0) {
@@ -1727,21 +1741,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17271741
};
17281742
let new_lt = generics
17291743
.as_ref()
1730-
.and_then(|g| {
1744+
.and_then(|(parent_g, g)| {
17311745
let possible = ["'a", "'b", "'c", "'d", "'e", "'f", "'g", "'h", "'i", "'j", "'k"];
1732-
let lts_names = g
1746+
let mut lts_names = g
17331747
.params
17341748
.iter()
17351749
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
17361750
.map(|p| p.name.as_str())
17371751
.collect::<Vec<_>>();
1752+
if let Some(g) = parent_g {
1753+
lts_names.extend(
1754+
g.params
1755+
.iter()
1756+
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
1757+
.map(|p| p.name.as_str()),
1758+
);
1759+
}
17381760
let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::<Vec<_>>();
17391761
possible.iter().filter(|&candidate| !lts.contains(&*candidate)).next().map(|s| *s)
17401762
})
17411763
.unwrap_or("'lt");
17421764
let add_lt_sugg = generics
17431765
.as_ref()
1744-
.and_then(|g| g.params.first())
1766+
.and_then(|(_, g)| g.params.first())
17451767
.and_then(|param| param.def_id.as_local())
17461768
.map(|def_id| {
17471769
(hir.span(hir.as_local_hir_id(def_id)).shrink_to_lo(), format!("{}, ", new_lt))

src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
121121
(Some(ret_span), _) => (
122122
ty_sub.span,
123123
ret_span,
124-
"this parameter and the return type are declared \
125-
with different lifetimes..."
124+
"this parameter and the return type are declared with different lifetimes..."
126125
.to_owned(),
127126
format!("...but data{} is returned here", span_label_var1),
128127
),
129128
(_, Some(ret_span)) => (
130129
ty_sup.span,
131130
ret_span,
132-
"this parameter and the return type are declared \
133-
with different lifetimes..."
131+
"this parameter and the return type are declared with different lifetimes..."
134132
.to_owned(),
135133
format!("...but data{} is returned here", span_label_var1),
136134
),

src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,30 @@ LL | | }
5656
| |_^
5757

5858
error[E0311]: the parameter type `G` may not live long enough
59-
--> $DIR/missing-lifetimes-in-signature.rs:58:45
59+
--> $DIR/missing-lifetimes-in-signature.rs:59:58
60+
|
61+
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
62+
| ^^^^^^^^^^^^^^^^^^
63+
|
64+
note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5...
65+
--> $DIR/missing-lifetimes-in-signature.rs:59:5
66+
|
67+
LL | / fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
68+
LL | |
69+
LL | | move || {
70+
LL | | *dest = g.get();
71+
LL | | }
72+
LL | | }
73+
| |_____^
74+
75+
error[E0311]: the parameter type `G` may not live long enough
76+
--> $DIR/missing-lifetimes-in-signature.rs:68:45
6077
|
6178
LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
6279
| ^^^^^^^^^^^^^^^^^^^^^^^
6380
|
64-
note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 58:1...
65-
--> $DIR/missing-lifetimes-in-signature.rs:58:1
81+
note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 68:1...
82+
--> $DIR/missing-lifetimes-in-signature.rs:68:1
6683
|
6784
LL | / fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
6885
LL | |
@@ -74,7 +91,7 @@ LL | | }
7491
| |_^
7592

7693
error[E0621]: explicit lifetime required in the type of `dest`
77-
--> $DIR/missing-lifetimes-in-signature.rs:63:5
94+
--> $DIR/missing-lifetimes-in-signature.rs:73:5
7895
|
7996
LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
8097
| ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
@@ -85,14 +102,14 @@ LL | | }
85102
| |_____^ lifetime `'a` required
86103

87104
error[E0309]: the parameter type `G` may not live long enough
88-
--> $DIR/missing-lifetimes-in-signature.rs:69:44
105+
--> $DIR/missing-lifetimes-in-signature.rs:79:44
89106
|
90107
LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
91108
| ^^^^^^^^^^^^^^^^^^
92109
|
93110
= help: consider adding an explicit lifetime bound `G: 'a`...
94111

95-
error: aborting due to 7 previous errors
112+
error: aborting due to 8 previous errors
96113

97114
Some errors have detailed explanations: E0261, E0309, E0621.
98115
For more information about an error, try `rustc --explain E0261`.

src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ where
5454
}
5555
}
5656

57+
// Same as above, but show that we pay attention to lifetime names from parent item
58+
impl<'a> Foo {
59+
fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
60+
//~^ ERROR the parameter type `G` may not live long enough
61+
move || {
62+
*dest = g.get();
63+
}
64+
}
65+
}
66+
5767
// After applying suggestion for `qux`:
5868
fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
5969
//~^ ERROR explicit lifetime required in the type of `dest`

src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,23 +87,49 @@ help: consider introducing an explicit lifetime bound
8787
LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b
8888
| ^^^ ^^^^^^^ ^^^^
8989

90+
error[E0311]: the parameter type `G` may not live long enough
91+
--> $DIR/missing-lifetimes-in-signature.rs:59:58
92+
|
93+
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
94+
| ^^^^^^^^^^^^^^^^^^
95+
|
96+
note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5...
97+
--> $DIR/missing-lifetimes-in-signature.rs:59:5
98+
|
99+
LL | / fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
100+
LL | |
101+
LL | | move || {
102+
LL | | *dest = g.get();
103+
LL | | }
104+
LL | | }
105+
| |_____^
106+
note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:61:9: 63:10 g:G, dest:&mut T]` will meet its required lifetime bounds
107+
--> $DIR/missing-lifetimes-in-signature.rs:59:58
108+
|
109+
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
110+
| ^^^^^^^^^^^^^^^^^^
111+
help: consider introducing an explicit lifetime bound
112+
|
113+
LL | fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c {
114+
| ^^^ ^^^^^^^ ^^^^
115+
90116
error[E0621]: explicit lifetime required in the type of `dest`
91-
--> $DIR/missing-lifetimes-in-signature.rs:58:45
117+
--> $DIR/missing-lifetimes-in-signature.rs:68:45
92118
|
93119
LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
94120
| ------ ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
95121
| |
96122
| help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
97123

98124
error[E0309]: the parameter type `G` may not live long enough
99-
--> $DIR/missing-lifetimes-in-signature.rs:69:44
125+
--> $DIR/missing-lifetimes-in-signature.rs:79:44
100126
|
101127
LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
102-
| - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:74:5: 76:6 g:G, dest:&mut T]` will meet its required lifetime bounds
128+
| - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:84:5: 86:6 g:G, dest:&mut T]` will meet its required lifetime bounds
103129
| |
104130
| help: consider adding an explicit lifetime bound...: `G: 'a`
105131

106-
error: aborting due to 6 previous errors
132+
error: aborting due to 7 previous errors
107133

108134
Some errors have detailed explanations: E0261, E0309, E0621.
109135
For more information about an error, try `rustc --explain E0261`.

0 commit comments

Comments
 (0)