diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2022-11-06 09:45:34 +0000 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2022-11-24 17:48:42 +0000 |
| commit | 41090346d844b625ac58004066184d34a9d24f99 (patch) | |
| tree | 9d26579f7e57a694984e5fc44b60e2487be994b2 | |
| parent | 5f5e7a8eec4b69708005014ec322ba71caecdad1 (diff) | |
| download | rust-41090346d844b625ac58004066184d34a9d24f99.tar.gz rust-41090346d844b625ac58004066184d34a9d24f99.zip | |
Change how suggested lifetime args are computed.
11 files changed, 83 insertions, 55 deletions
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 9c77387c238..4451db19f5c 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -296,25 +296,35 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { ) -> String { debug!(?path_hir_id); + // If there was already a lifetime among the arguments, just replicate that one. + if let Some(lt) = self.gen_args.args.iter().find_map(|arg| match arg { + hir::GenericArg::Lifetime(lt) => Some(lt), + _ => None, + }) { + return std::iter::repeat(lt.to_string()) + .take(num_params_to_take) + .collect::<Vec<_>>() + .join(", "); + } + let mut ret = Vec::new(); + let mut ty_id = None; for (id, node) in self.tcx.hir().parent_iter(path_hir_id) { debug!(?id); - let params = if let Some(generics) = node.generics() { - generics.params - } else if let hir::Node::Ty(ty) = node - && let hir::TyKind::BareFn(bare_fn) = ty.kind - { - bare_fn.generic_params - } else { - &[] - }; - ret.extend(params.iter().filter_map(|p| { - let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } - = p.kind - else { return None }; - let hir::ParamName::Plain(name) = p.name else { return None }; - Some(name.to_string()) - })); + if let hir::Node::Ty(_) = node { + ty_id = Some(id); + } + + // Suggest `'_` when in function parameter or elided function return. + if let Some(fn_decl) = node.fn_decl() && let Some(ty_id) = ty_id { + let in_arg = fn_decl.inputs.iter().any(|t| t.hir_id == ty_id); + let in_ret = matches!(fn_decl.output, hir::FnRetTy::Return(ty) if ty.hir_id == ty_id); + + if in_arg || (in_ret && fn_decl.lifetime_elision_allowed) { + return std::iter::repeat("'_".to_owned()).take(num_params_to_take).collect::<Vec<_>>().join(", "); + } + } + // Suggest `'static` when in const/static item-like. if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Static { .. } | hir::ItemKind::Const { .. }, @@ -334,11 +344,29 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { }) | hir::Node::AnonConst(..) = node { - ret.extend( - std::iter::repeat("'static".to_owned()) - .take(num_params_to_take.saturating_sub(ret.len())), - ); + return std::iter::repeat("'static".to_owned()) + .take(num_params_to_take.saturating_sub(ret.len())) + .collect::<Vec<_>>() + .join(", "); } + + let params = if let Some(generics) = node.generics() { + generics.params + } else if let hir::Node::Ty(ty) = node + && let hir::TyKind::BareFn(bare_fn) = ty.kind + { + bare_fn.generic_params + } else { + &[] + }; + ret.extend(params.iter().filter_map(|p| { + let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } + = p.kind + else { return None }; + let hir::ParamName::Plain(name) = p.name else { return None }; + Some(name.to_string()) + })); + if ret.len() >= num_params_to_take { return ret[..num_params_to_take].join(", "); } diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr index 9deb9b26588..8278edabe3a 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr @@ -11,7 +11,7 @@ LL | type Y<'a>; | ^ -- help: add missing lifetime argument | -LL | fn f2<'a>(arg: Box<dyn X<Y<'a, 1> = &'a ()>>) {} +LL | fn f2<'a>(arg: Box<dyn X<Y<'_, 1> = &'a ()>>) {} | +++ error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied diff --git a/src/test/ui/constructor-lifetime-args.stderr b/src/test/ui/constructor-lifetime-args.stderr index b97b6faa3be..bc1141b16c5 100644 --- a/src/test/ui/constructor-lifetime-args.stderr +++ b/src/test/ui/constructor-lifetime-args.stderr @@ -13,8 +13,8 @@ LL | struct S<'a, 'b>(&'a u8, &'b u8); | ^ -- -- help: add missing lifetime argument | -LL | S::<'static, 'b>(&0, &0); - | ++++ +LL | S::<'static, 'static>(&0, &0); + | +++++++++ error[E0107]: this struct takes 2 lifetime arguments but 3 lifetime arguments were supplied --> $DIR/constructor-lifetime-args.rs:19:5 @@ -45,8 +45,8 @@ LL | enum E<'a, 'b> { | ^ -- -- help: add missing lifetime argument | -LL | E::V::<'static, 'b>(&0); - | ++++ +LL | E::V::<'static, 'static>(&0); + | +++++++++ error[E0107]: this enum takes 2 lifetime arguments but 3 lifetime arguments were supplied --> $DIR/constructor-lifetime-args.rs:24:8 diff --git a/src/test/ui/generic-associated-types/elided-in-expr-position.stderr b/src/test/ui/generic-associated-types/elided-in-expr-position.stderr index 20f35c3c137..a9996123f23 100644 --- a/src/test/ui/generic-associated-types/elided-in-expr-position.stderr +++ b/src/test/ui/generic-associated-types/elided-in-expr-position.stderr @@ -11,7 +11,7 @@ LL | type Assoc<'a> where Self: 'a; | ^^^^^ -- help: add missing lifetime argument | -LL | fn g(&self) -> Self::Assoc<'a>; +LL | fn g(&self) -> Self::Assoc<'_>; | ~~~~~~~~~ error[E0107]: missing generics for associated type `Trait::Assoc` @@ -27,7 +27,7 @@ LL | type Assoc<'a> where Self: 'a; | ^^^^^ -- help: add missing lifetime argument | -LL | fn g(&self) -> Self::Assoc<'a> { +LL | fn g(&self) -> Self::Assoc<'_> { | ~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr index e55a21e19f0..165779796e0 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr +++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr @@ -36,7 +36,7 @@ LL | type Y<'a>; | ^ -- help: add missing lifetime argument | -LL | fn foo<'a>(arg: Box<dyn X<Y('a, 'a) = &'a ()>>) {} +LL | fn foo<'a>(arg: Box<dyn X<Y('_, 'a) = &'a ()>>) {} | +++ error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied @@ -66,7 +66,7 @@ LL | type Y<'a>; | ^ -- help: add missing lifetime argument | -LL | fn bar<'a>(arg: Box<dyn X<Y('a) = ()>>) {} +LL | fn bar<'a>(arg: Box<dyn X<Y('_) = ()>>) {} | ++ error: aborting due to 6 previous errors diff --git a/src/test/ui/generic-associated-types/issue-81862.stderr b/src/test/ui/generic-associated-types/issue-81862.stderr index ba798084673..9e21c567c73 100644 --- a/src/test/ui/generic-associated-types/issue-81862.stderr +++ b/src/test/ui/generic-associated-types/issue-81862.stderr @@ -11,7 +11,7 @@ LL | type Item<'a>; | ^^^^ -- help: add missing lifetime argument | -LL | fn next(&mut self) -> Option<Self::Item<'a>>; +LL | fn next(&mut self) -> Option<Self::Item<'_>>; | ~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/missing_lifetime_args.stderr b/src/test/ui/generic-associated-types/missing_lifetime_args.stderr index 0ad1f1f8c4d..752587c25a7 100644 --- a/src/test/ui/generic-associated-types/missing_lifetime_args.stderr +++ b/src/test/ui/generic-associated-types/missing_lifetime_args.stderr @@ -11,7 +11,7 @@ LL | type Y<'a, 'b>; | ^ -- -- help: add missing lifetime arguments | -LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'c, 'd> = (&'c u32, &'d u32)>>) {} +LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'_, '_> = (&'c u32, &'d u32)>>) {} | ~~~~~~~~~ error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied @@ -47,7 +47,7 @@ LL | struct Foo<'a, 'b, 'c> { | ^^^ -- -- -- help: add missing lifetime arguments | -LL | fn f<'a>(_arg: Foo<'a, 'b, 'c>) {} +LL | fn f<'a>(_arg: Foo<'a, 'a, 'a>) {} | ++++++++ error: aborting due to 3 previous errors diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr index e00a414efb9..0a09ec5dc49 100644 --- a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr +++ b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr @@ -11,7 +11,7 @@ LL | type Y<'a>; | ^ -- help: add missing lifetime argument | -LL | fn f2<'a>(arg : Box<dyn X<Y<'a, 1> = &'a ()>>) {} +LL | fn f2<'a>(arg : Box<dyn X<Y<'_, 1> = &'a ()>>) {} | +++ error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr index 388c23fc24f..0475eb908a7 100644 --- a/src/test/ui/generics/wrong-number-of-args.stderr +++ b/src/test/ui/generics/wrong-number-of-args.stderr @@ -812,8 +812,8 @@ LL | trait GenericLifetimeLifetimeAT<'a, 'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -- -- help: add missing lifetime argument | -LL | type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'b, AssocTy=()>>; - | ++++ +LL | type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'static, AssocTy=()>>; + | +++++++++ error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:287:26 @@ -846,8 +846,8 @@ LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- -- help: add missing lifetime argument | -LL | type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'b, AssocTy=()>>; - | ++++ +LL | type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'static, AssocTy=()>>; + | +++++++++ error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:294:26 @@ -880,8 +880,8 @@ LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- -- help: add missing lifetime argument | -LL | type C = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'b, (), AssocTy=()>>; - | ++++ +LL | type C = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'static, (), AssocTy=()>>; + | +++++++++ error[E0107]: missing generics for struct `HashMap` --> $DIR/wrong-number-of-args.rs:310:18 diff --git a/src/test/ui/methods/method-call-lifetime-args-fail.stderr b/src/test/ui/methods/method-call-lifetime-args-fail.stderr index 835edb4b0ae..249b48ab194 100644 --- a/src/test/ui/methods/method-call-lifetime-args-fail.stderr +++ b/src/test/ui/methods/method-call-lifetime-args-fail.stderr @@ -13,8 +13,8 @@ LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } | ^^^^^ -- -- help: add missing lifetime argument | -LL | S.early::<'static, 'b>(); - | ++++ +LL | S.early::<'static, 'static>(); + | +++++++++ error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied --> $DIR/method-call-lifetime-args-fail.rs:18:7 @@ -213,8 +213,8 @@ LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } | ^^^^^ -- -- help: add missing lifetime argument | -LL | S::early::<'static, 'b>(S); - | ++++ +LL | S::early::<'static, 'static>(S); + | +++++++++ error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied --> $DIR/method-call-lifetime-args-fail.rs:65:8 diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr index 10fb28c1891..997bbb5e9b5 100644 --- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr +++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr @@ -166,8 +166,8 @@ LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- help: add missing lifetime argument | -LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); - | ++++ +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++++ error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied --> $DIR/missing-lifetime-specifier.rs:39:44 @@ -184,8 +184,8 @@ LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- help: add missing lifetime argument | -LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); - | ++++ +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++++ error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied --> $DIR/missing-lifetime-specifier.rs:39:44 @@ -202,8 +202,8 @@ LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- help: add missing lifetime argument | -LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); - | ++++ +LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++++ error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied --> $DIR/missing-lifetime-specifier.rs:39:44 @@ -256,8 +256,8 @@ LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- help: add missing lifetime argument | -LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); - | ++++ +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++++ error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied --> $DIR/missing-lifetime-specifier.rs:47:45 @@ -274,8 +274,8 @@ LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- help: add missing lifetime argument | -LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); - | ++++ +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++++ error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied --> $DIR/missing-lifetime-specifier.rs:47:45 @@ -292,8 +292,8 @@ LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- help: add missing lifetime argument | -LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new()); - | ++++ +LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); + | +++++++++ error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied --> $DIR/missing-lifetime-specifier.rs:47:45 |
