about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2023-11-15 18:00:43 +0000
committerEsteban Küber <esteban@kuber.com.ar>2023-11-20 23:44:37 +0000
commit85f26ade8dc3364f29a2c0b0d8f5fe2068df8969 (patch)
treeb215114727885740f7d7950d3327b01edd9e2ed7
parent2a92d820c79e56be8191bdf64e8b2dc7c96210df (diff)
downloadrust-85f26ade8dc3364f29a2c0b0d8f5fe2068df8969.tar.gz
rust-85f26ade8dc3364f29a2c0b0d8f5fe2068df8969.zip
Account for '_ in lifetime suggestion
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs19
-rw-r--r--tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr10
-rw-r--r--tests/ui/suggestions/impl-trait-missing-lifetime.stderr10
3 files changed, 35 insertions, 4 deletions
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 984516baa18..f7560d9949b 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -3079,6 +3079,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         } else {
                             "instead, you are more likely to want"
                         };
+                        let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand;
                         let mut sugg = vec![(lt.span, String::new())];
                         if let Some((kind, _span)) =
                             self.diagnostic_metadata.current_function
@@ -3092,6 +3093,17 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                             };
                             lt_finder.visit_ty(&ty);
 
+                            if let [Ty { span, kind: TyKind::Ref(_, mut_ty), ..}]
+                                = &lt_finder.seen[..]
+                            {
+                                // We might have a situation like
+                                // fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()>
+                                // but `lt.span` only points at `'_`, so to suggest `-> Option<()>`
+                                // we need to find a more accurate span to end up with
+                                // fn g<'a>(mut x: impl Iterator<Item = &'_ ()>) -> Option<()>
+                                sugg = vec![(span.with_hi(mut_ty.ty.span.lo()), String::new())];
+                                owned_sugg = true;
+                            }
                             if let Some(ty) = lt_finder.found {
                                 if let TyKind::Path(None, Path { segments, .. }) = &ty.kind
                                     && segments.len() == 1
@@ -3101,8 +3113,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                                     sugg = vec![
                                         (lt.span.with_hi(ty.span.hi()), "String".to_string()),
                                     ];
-                                }
-                                if let TyKind::Slice(inner_ty) = &ty.kind {
+                                } else if let TyKind::Slice(inner_ty) = &ty.kind {
                                     // Don't suggest `-> [T]`, suggest `-> Vec<T>`.
                                     sugg = vec![
                                         (lt.span.with_hi(inner_ty.span.lo()), "Vec<".to_string()),
@@ -3110,8 +3121,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                                     ];
                                 }
                             }
-                        };
-                        if lt.kind == MissingLifetimeKind::Ampersand {
+                        }
+                        if owned_sugg {
                             err.multipart_suggestion_verbose(
                                 format!("{pre} to return an owned value"),
                                 sugg,
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
index 383cba75e28..2dfaa731194 100644
--- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
@@ -55,6 +55,11 @@ help: consider introducing a named lifetime parameter
    |
 LL |     fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()> { x.next() }
    |         ++++                             ~~~                ~~~
+help: alternatively, you might want to return an owned value
+   |
+LL -     fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+LL +     fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() }
+   |
 
 error[E0106]: missing lifetime specifier
   --> $DIR/impl-trait-missing-lifetime-gated.rs:37:64
@@ -71,6 +76,11 @@ help: consider introducing a named lifetime parameter
    |
 LL |     async fn i<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()> { x.next() }
    |               ++++                             ~~~                ~~~
+help: alternatively, you might want to return an owned value
+   |
+LL -     async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+LL +     async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() }
+   |
 
 error[E0106]: missing lifetime specifier
   --> $DIR/impl-trait-missing-lifetime-gated.rs:47:37
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr
index 98b0ab82b3c..c1dbaae0649 100644
--- a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr
@@ -13,6 +13,11 @@ help: consider introducing a named lifetime parameter
    |
 LL | fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()> { x.next() }
    |     ++++                             ~~~                ~~~
+help: alternatively, you might want to return an owned value
+   |
+LL - fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+LL + fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() }
+   |
 
 error[E0106]: missing lifetime specifier
   --> $DIR/impl-trait-missing-lifetime.rs:16:60
@@ -29,6 +34,11 @@ help: consider introducing a named lifetime parameter
    |
 LL | async fn i<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()> { x.next() }
    |           ++++                             ~~~                ~~~
+help: alternatively, you might want to return an owned value
+   |
+LL - async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+LL + async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() }
+   |
 
 error: lifetime may not live long enough
   --> $DIR/impl-trait-missing-lifetime.rs:16:69