about summary refs log tree commit diff
path: root/compiler/rustc_errors/src
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2021-05-10 16:15:00 +0200
committerGitHub <noreply@github.com>2021-05-10 16:15:00 +0200
commit0740015d59c8c35c803f5f4a0b2aab112e0531aa (patch)
treef62ac654c143a9dbf6cd9c85717d8d567200586e /compiler/rustc_errors/src
parent1b30245ea1286df96d673015c4519c861e06977a (diff)
parent2448c7698ef186ead88bd7980f2cac28c55111a8 (diff)
downloadrust-0740015d59c8c35c803f5f4a0b2aab112e0531aa.tar.gz
rust-0740015d59c8c35c803f5f4a0b2aab112e0531aa.zip
Rollup merge of #85050 - FabianWolff:issue-84592, r=jackh726
Fix suggestions for missing return type lifetime specifiers

This pull request aims to fix #84592. The issue is that the current code seems to assume that there is only a single relevant span pointing to the missing lifetime, and only looks at the first one:
https://github.com/rust-lang/rust/blob/e5f83d24aee866a14753a7cedbb4e301dfe5bef5/compiler/rustc_resolve/src/late/lifetimes.rs#L2959

This is incorrect, though, and leads to incorrect error messages and invalid suggestions. For instance, the example from #84592:
```rust
struct TwoLifetimes<'x, 'y> {
    x: &'x (),
    y: &'y (),
}

fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> {
    TwoLifetimes { x: &(), y: &() }
}
```
currently leads to:
```
error[E0106]: missing lifetime specifiers
 --> src/main.rs:6:57
  |
6 | fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> {
  |                            ---     ---                  ^^ expected 2 lifetime parameters
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b`
help: consider introducing a named lifetime parameter
  |
6 | fn two_lifetimes_needed<'a>(a: &'a (), b: &'a ()) -> TwoLifetimes<'_<'a, 'a>, '_> {
  |                        ^^^^    ^^^^^^     ^^^^^^                  ^^^^^^^^^^
```
There are two problems:
- The error message is wrong. There is only _one_ lifetime parameter expected at the location pointed to by the error message (and another one at a separate location).
- The suggestion is incorrect and will not lead to correct code.

With the changes in this PR, I get the following output:
```
error[E0106]: missing lifetime specifiers
 --> p.rs:6:57
  |
6 | fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> {
  |                            ---     ---                  ^^  ^^ expected named lifetime parameter
  |                                                         |
  |                                                         expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b`
help: consider introducing a named lifetime parameter
  |
6 | fn two_lifetimes_needed<'a>(a: &'a (), b: &'a ()) -> TwoLifetimes<'a, 'a> {
  |                        ^^^^    ^^^^^^     ^^^^^^                  ^^  ^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0106`.
```
Mainly, I changed `add_missing_lifetime_specifiers_label()` to receive a _vector_ of spans (and counts) instead of just one, and adjusted its body accordingly.
Diffstat (limited to 'compiler/rustc_errors/src')
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs18
1 files changed, 17 insertions, 1 deletions
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index b2f6a0c1014..14ccced2c6a 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -283,6 +283,22 @@ impl Diagnostic {
         suggestion: Vec<(Span, String)>,
         applicability: Applicability,
     ) -> &mut Self {
+        self.multipart_suggestion_with_style(
+            msg,
+            suggestion,
+            applicability,
+            SuggestionStyle::ShowCode,
+        )
+    }
+
+    /// [`Diagnostic::multipart_suggestion()`] but you can set the [`SuggestionStyle`].
+    pub fn multipart_suggestion_with_style(
+        &mut self,
+        msg: &str,
+        suggestion: Vec<(Span, String)>,
+        applicability: Applicability,
+        style: SuggestionStyle,
+    ) -> &mut Self {
         assert!(!suggestion.is_empty());
         self.suggestions.push(CodeSuggestion {
             substitutions: vec![Substitution {
@@ -292,7 +308,7 @@ impl Diagnostic {
                     .collect(),
             }],
             msg: msg.to_owned(),
-            style: SuggestionStyle::ShowCode,
+            style,
             applicability,
             tool_metadata: Default::default(),
         });