about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2021-05-20 17:56:56 +0200
committerGitHub <noreply@github.com>2021-05-20 17:56:56 +0200
commit67d5435695fa2a62d7a075c50b42ea83a5d19f0d (patch)
treeb23b712ad59d53a4bb510a6cfbaf5e1e556e5485
parentddc376c03d13931bbba5550d6e8436e6ee8173cb (diff)
parent363eacd8d336e273f234d320dba26e67f7399616 (diff)
downloadrust-67d5435695fa2a62d7a075c50b42ea83a5d19f0d.tar.gz
rust-67d5435695fa2a62d7a075c50b42ea83a5d19f0d.zip
Rollup merge of #85375 - SkiFire13:fix-85347, r=jackh726
Fix missing lifetimes diagnostics after #83759

In #83759 while rebasing I didn't realize there was a new function for suggesting to add lifetime arguments. It relied on some invariants, namely that if a generic type/trait has angle brackets then it must have some generic argument, which is now no longer true. This PR updates that function to handle the new invariants.

This also adds a new regression test but I'm not sure if that's the correct place for it.

Fixes #85347
-rw-r--r--compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs53
-rw-r--r--src/test/ui/suggestions/issue-85347.rs10
-rw-r--r--src/test/ui/suggestions/issue-85347.stderr19
3 files changed, 45 insertions, 37 deletions
diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
index 56f288ff051..aed36b12f3a 100644
--- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
@@ -509,44 +509,23 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
             }
 
             AngleBrackets::Available => {
-                // angle brackets exist, so we insert missing arguments after the existing args
-
-                assert!(!self.gen_args.args.is_empty());
-
-                if self.num_provided_lifetime_args() > 0 {
-                    let last_lt_arg_span = self.gen_args.args
-                        [self.num_provided_lifetime_args() - 1]
-                        .span()
-                        .shrink_to_hi();
-                    let source_map = self.tcx.sess.source_map();
-
-                    if let Ok(last_gen_arg) = source_map.span_to_snippet(last_lt_arg_span) {
-                        let sugg = format!("{}, {}", last_gen_arg, suggested_args);
-
-                        err.span_suggestion_verbose(
-                            last_lt_arg_span,
-                            &msg,
-                            sugg,
-                            Applicability::HasPlaceholders,
-                        );
-                    }
+                let (sugg_span, is_first) = if self.num_provided_lifetime_args() == 0 {
+                    (self.gen_args.span().unwrap().shrink_to_lo(), true)
                 } else {
-                    // Non-lifetime arguments included in `gen_args` -> insert missing lifetimes before
-                    // existing arguments
-                    let first_arg_span = self.gen_args.args[0].span().shrink_to_lo();
-                    let source_map = self.tcx.sess.source_map();
-
-                    if let Ok(first_gen_arg) = source_map.span_to_snippet(first_arg_span) {
-                        let sugg = format!("{}, {}", suggested_args, first_gen_arg);
-
-                        err.span_suggestion_verbose(
-                            first_arg_span,
-                            &msg,
-                            sugg,
-                            Applicability::HasPlaceholders,
-                        );
-                    }
-                }
+                    let last_lt = &self.gen_args.args[self.num_provided_lifetime_args() - 1];
+                    (last_lt.span().shrink_to_hi(), false)
+                };
+                let has_non_lt_args = self.num_provided_type_or_const_args() != 0;
+                let has_bindings = !self.gen_args.bindings.is_empty();
+
+                let sugg_prefix = if is_first { "" } else { ", " };
+                let sugg_suffix =
+                    if is_first && (has_non_lt_args || has_bindings) { ", " } else { "" };
+
+                let sugg = format!("{}{}{}", sugg_prefix, suggested_args, sugg_suffix);
+                debug!("sugg: {:?}", sugg);
+
+                err.span_suggestion_verbose(sugg_span, &msg, sugg, Applicability::HasPlaceholders);
             }
             AngleBrackets::Implied => {
                 // We never encounter missing lifetimes in situations in which lifetimes are elided
diff --git a/src/test/ui/suggestions/issue-85347.rs b/src/test/ui/suggestions/issue-85347.rs
new file mode 100644
index 00000000000..f08e38689d6
--- /dev/null
+++ b/src/test/ui/suggestions/issue-85347.rs
@@ -0,0 +1,10 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+use std::ops::Deref;
+trait Foo {
+    type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+    //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+    //~| HELP add missing
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-85347.stderr b/src/test/ui/suggestions/issue-85347.stderr
new file mode 100644
index 00000000000..60594baa29c
--- /dev/null
+++ b/src/test/ui/suggestions/issue-85347.stderr
@@ -0,0 +1,19 @@
+error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+  --> $DIR/issue-85347.rs:5:42
+   |
+LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+   |                                          ^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-85347.rs:5:10
+   |
+LL |     type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
+   |          ^^^ --
+help: add missing lifetime argument
+   |
+LL |     type Bar<'a>: Deref<Target = <Self>::Bar<'a, Target = Self>>;
+   |                                              ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.