about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2022-11-06 09:45:34 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2022-11-24 17:48:42 +0000
commit41090346d844b625ac58004066184d34a9d24f99 (patch)
tree9d26579f7e57a694984e5fc44b60e2487be994b2
parent5f5e7a8eec4b69708005014ec322ba71caecdad1 (diff)
downloadrust-41090346d844b625ac58004066184d34a9d24f99.tar.gz
rust-41090346d844b625ac58004066184d34a9d24f99.zip
Change how suggested lifetime args are computed.
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs68
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr2
-rw-r--r--src/test/ui/constructor-lifetime-args.stderr8
-rw-r--r--src/test/ui/generic-associated-types/elided-in-expr-position.stderr4
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr4
-rw-r--r--src/test/ui/generic-associated-types/issue-81862.stderr2
-rw-r--r--src/test/ui/generic-associated-types/missing_lifetime_args.stderr4
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr2
-rw-r--r--src/test/ui/generics/wrong-number-of-args.stderr12
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-fail.stderr8
-rw-r--r--src/test/ui/suggestions/missing-lifetime-specifier.stderr24
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