Skip to content

Commit 4109034

Browse files
committed
Change how suggested lifetime args are computed.
1 parent 5f5e7a8 commit 4109034

11 files changed

+83
-55
lines changed

compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs

+48-20
Original file line numberDiff line numberDiff line change
@@ -296,25 +296,35 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
296296
) -> String {
297297
debug!(?path_hir_id);
298298

299+
// If there was already a lifetime among the arguments, just replicate that one.
300+
if let Some(lt) = self.gen_args.args.iter().find_map(|arg| match arg {
301+
hir::GenericArg::Lifetime(lt) => Some(lt),
302+
_ => None,
303+
}) {
304+
return std::iter::repeat(lt.to_string())
305+
.take(num_params_to_take)
306+
.collect::<Vec<_>>()
307+
.join(", ");
308+
}
309+
299310
let mut ret = Vec::new();
311+
let mut ty_id = None;
300312
for (id, node) in self.tcx.hir().parent_iter(path_hir_id) {
301313
debug!(?id);
302-
let params = if let Some(generics) = node.generics() {
303-
generics.params
304-
} else if let hir::Node::Ty(ty) = node
305-
&& let hir::TyKind::BareFn(bare_fn) = ty.kind
306-
{
307-
bare_fn.generic_params
308-
} else {
309-
&[]
310-
};
311-
ret.extend(params.iter().filter_map(|p| {
312-
let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
313-
= p.kind
314-
else { return None };
315-
let hir::ParamName::Plain(name) = p.name else { return None };
316-
Some(name.to_string())
317-
}));
314+
if let hir::Node::Ty(_) = node {
315+
ty_id = Some(id);
316+
}
317+
318+
// Suggest `'_` when in function parameter or elided function return.
319+
if let Some(fn_decl) = node.fn_decl() && let Some(ty_id) = ty_id {
320+
let in_arg = fn_decl.inputs.iter().any(|t| t.hir_id == ty_id);
321+
let in_ret = matches!(fn_decl.output, hir::FnRetTy::Return(ty) if ty.hir_id == ty_id);
322+
323+
if in_arg || (in_ret && fn_decl.lifetime_elision_allowed) {
324+
return std::iter::repeat("'_".to_owned()).take(num_params_to_take).collect::<Vec<_>>().join(", ");
325+
}
326+
}
327+
318328
// Suggest `'static` when in const/static item-like.
319329
if let hir::Node::Item(hir::Item {
320330
kind: hir::ItemKind::Static { .. } | hir::ItemKind::Const { .. },
@@ -334,11 +344,29 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
334344
})
335345
| hir::Node::AnonConst(..) = node
336346
{
337-
ret.extend(
338-
std::iter::repeat("'static".to_owned())
339-
.take(num_params_to_take.saturating_sub(ret.len())),
340-
);
347+
return std::iter::repeat("'static".to_owned())
348+
.take(num_params_to_take.saturating_sub(ret.len()))
349+
.collect::<Vec<_>>()
350+
.join(", ");
341351
}
352+
353+
let params = if let Some(generics) = node.generics() {
354+
generics.params
355+
} else if let hir::Node::Ty(ty) = node
356+
&& let hir::TyKind::BareFn(bare_fn) = ty.kind
357+
{
358+
bare_fn.generic_params
359+
} else {
360+
&[]
361+
};
362+
ret.extend(params.iter().filter_map(|p| {
363+
let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
364+
= p.kind
365+
else { return None };
366+
let hir::ParamName::Plain(name) = p.name else { return None };
367+
Some(name.to_string())
368+
}));
369+
342370
if ret.len() >= num_params_to_take {
343371
return ret[..num_params_to_take].join(", ");
344372
}

src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ LL | type Y<'a>;
1111
| ^ --
1212
help: add missing lifetime argument
1313
|
14-
LL | fn f2<'a>(arg: Box<dyn X<Y<'a, 1> = &'a ()>>) {}
14+
LL | fn f2<'a>(arg: Box<dyn X<Y<'_, 1> = &'a ()>>) {}
1515
| +++
1616

1717
error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied

src/test/ui/constructor-lifetime-args.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ LL | struct S<'a, 'b>(&'a u8, &'b u8);
1313
| ^ -- --
1414
help: add missing lifetime argument
1515
|
16-
LL | S::<'static, 'b>(&0, &0);
17-
| ++++
16+
LL | S::<'static, 'static>(&0, &0);
17+
| +++++++++
1818

1919
error[E0107]: this struct takes 2 lifetime arguments but 3 lifetime arguments were supplied
2020
--> $DIR/constructor-lifetime-args.rs:19:5
@@ -45,8 +45,8 @@ LL | enum E<'a, 'b> {
4545
| ^ -- --
4646
help: add missing lifetime argument
4747
|
48-
LL | E::V::<'static, 'b>(&0);
49-
| ++++
48+
LL | E::V::<'static, 'static>(&0);
49+
| +++++++++
5050

5151
error[E0107]: this enum takes 2 lifetime arguments but 3 lifetime arguments were supplied
5252
--> $DIR/constructor-lifetime-args.rs:24:8

src/test/ui/generic-associated-types/elided-in-expr-position.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ LL | type Assoc<'a> where Self: 'a;
1111
| ^^^^^ --
1212
help: add missing lifetime argument
1313
|
14-
LL | fn g(&self) -> Self::Assoc<'a>;
14+
LL | fn g(&self) -> Self::Assoc<'_>;
1515
| ~~~~~~~~~
1616

1717
error[E0107]: missing generics for associated type `Trait::Assoc`
@@ -27,7 +27,7 @@ LL | type Assoc<'a> where Self: 'a;
2727
| ^^^^^ --
2828
help: add missing lifetime argument
2929
|
30-
LL | fn g(&self) -> Self::Assoc<'a> {
30+
LL | fn g(&self) -> Self::Assoc<'_> {
3131
| ~~~~~~~~~
3232

3333
error: aborting due to 2 previous errors

src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ LL | type Y<'a>;
3636
| ^ --
3737
help: add missing lifetime argument
3838
|
39-
LL | fn foo<'a>(arg: Box<dyn X<Y('a, 'a) = &'a ()>>) {}
39+
LL | fn foo<'a>(arg: Box<dyn X<Y('_, 'a) = &'a ()>>) {}
4040
| +++
4141

4242
error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
@@ -66,7 +66,7 @@ LL | type Y<'a>;
6666
| ^ --
6767
help: add missing lifetime argument
6868
|
69-
LL | fn bar<'a>(arg: Box<dyn X<Y('a) = ()>>) {}
69+
LL | fn bar<'a>(arg: Box<dyn X<Y('_) = ()>>) {}
7070
| ++
7171

7272
error: aborting due to 6 previous errors

src/test/ui/generic-associated-types/issue-81862.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ LL | type Item<'a>;
1111
| ^^^^ --
1212
help: add missing lifetime argument
1313
|
14-
LL | fn next(&mut self) -> Option<Self::Item<'a>>;
14+
LL | fn next(&mut self) -> Option<Self::Item<'_>>;
1515
| ~~~~~~~~
1616

1717
error: aborting due to previous error

src/test/ui/generic-associated-types/missing_lifetime_args.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ LL | type Y<'a, 'b>;
1111
| ^ -- --
1212
help: add missing lifetime arguments
1313
|
14-
LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'c, 'd> = (&'c u32, &'d u32)>>) {}
14+
LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'_, '_> = (&'c u32, &'d u32)>>) {}
1515
| ~~~~~~~~~
1616

1717
error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied
@@ -47,7 +47,7 @@ LL | struct Foo<'a, 'b, 'c> {
4747
| ^^^ -- -- --
4848
help: add missing lifetime arguments
4949
|
50-
LL | fn f<'a>(_arg: Foo<'a, 'b, 'c>) {}
50+
LL | fn f<'a>(_arg: Foo<'a, 'a, 'a>) {}
5151
| ++++++++
5252

5353
error: aborting due to 3 previous errors

src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ LL | type Y<'a>;
1111
| ^ --
1212
help: add missing lifetime argument
1313
|
14-
LL | fn f2<'a>(arg : Box<dyn X<Y<'a, 1> = &'a ()>>) {}
14+
LL | fn f2<'a>(arg : Box<dyn X<Y<'_, 1> = &'a ()>>) {}
1515
| +++
1616

1717
error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied

src/test/ui/generics/wrong-number-of-args.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -812,8 +812,8 @@ LL | trait GenericLifetimeLifetimeAT<'a, 'b> {
812812
| ^^^^^^^^^^^^^^^^^^^^^^^^^ -- --
813813
help: add missing lifetime argument
814814
|
815-
LL | type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'b, AssocTy=()>>;
816-
| ++++
815+
LL | type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'static, AssocTy=()>>;
816+
| +++++++++
817817

818818
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
819819
--> $DIR/wrong-number-of-args.rs:287:26
@@ -846,8 +846,8 @@ LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> {
846846
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- --
847847
help: add missing lifetime argument
848848
|
849-
LL | type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'b, AssocTy=()>>;
850-
| ++++
849+
LL | type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'static, AssocTy=()>>;
850+
| +++++++++
851851

852852
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
853853
--> $DIR/wrong-number-of-args.rs:294:26
@@ -880,8 +880,8 @@ LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> {
880880
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- --
881881
help: add missing lifetime argument
882882
|
883-
LL | type C = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'b, (), AssocTy=()>>;
884-
| ++++
883+
LL | type C = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'static, (), AssocTy=()>>;
884+
| +++++++++
885885

886886
error[E0107]: missing generics for struct `HashMap`
887887
--> $DIR/wrong-number-of-args.rs:310:18

src/test/ui/methods/method-call-lifetime-args-fail.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
1313
| ^^^^^ -- --
1414
help: add missing lifetime argument
1515
|
16-
LL | S.early::<'static, 'b>();
17-
| ++++
16+
LL | S.early::<'static, 'static>();
17+
| +++++++++
1818

1919
error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
2020
--> $DIR/method-call-lifetime-args-fail.rs:18:7
@@ -213,8 +213,8 @@ LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
213213
| ^^^^^ -- --
214214
help: add missing lifetime argument
215215
|
216-
LL | S::early::<'static, 'b>(S);
217-
| ++++
216+
LL | S::early::<'static, 'static>(S);
217+
| +++++++++
218218

219219
error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
220220
--> $DIR/method-call-lifetime-args-fail.rs:65:8

src/test/ui/suggestions/missing-lifetime-specifier.stderr

+12-12
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ LL | pub union Qux<'t, 'k, I> {
166166
| ^^^ -- --
167167
help: add missing lifetime argument
168168
|
169-
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
170-
| ++++
169+
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
170+
| +++++++++
171171

172172
error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
173173
--> $DIR/missing-lifetime-specifier.rs:39:44
@@ -184,8 +184,8 @@ LL | pub union Qux<'t, 'k, I> {
184184
| ^^^ -- --
185185
help: add missing lifetime argument
186186
|
187-
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
188-
| ++++
187+
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
188+
| +++++++++
189189

190190
error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
191191
--> $DIR/missing-lifetime-specifier.rs:39:44
@@ -202,8 +202,8 @@ LL | pub union Qux<'t, 'k, I> {
202202
| ^^^ -- --
203203
help: add missing lifetime argument
204204
|
205-
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
206-
| ++++
205+
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
206+
| +++++++++
207207

208208
error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
209209
--> $DIR/missing-lifetime-specifier.rs:39:44
@@ -256,8 +256,8 @@ LL | trait Tar<'t, 'k, I> {}
256256
| ^^^ -- --
257257
help: add missing lifetime argument
258258
|
259-
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
260-
| ++++
259+
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
260+
| +++++++++
261261

262262
error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
263263
--> $DIR/missing-lifetime-specifier.rs:47:45
@@ -274,8 +274,8 @@ LL | trait Tar<'t, 'k, I> {}
274274
| ^^^ -- --
275275
help: add missing lifetime argument
276276
|
277-
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
278-
| ++++
277+
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
278+
| +++++++++
279279

280280
error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
281281
--> $DIR/missing-lifetime-specifier.rs:47:45
@@ -292,8 +292,8 @@ LL | trait Tar<'t, 'k, I> {}
292292
| ^^^ -- --
293293
help: add missing lifetime argument
294294
|
295-
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
296-
| ++++
295+
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
296+
| +++++++++
297297

298298
error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
299299
--> $DIR/missing-lifetime-specifier.rs:47:45

0 commit comments

Comments
 (0)