about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-10-17 21:07:31 -0700
committerEsteban Küber <esteban@kuber.com.ar>2018-10-22 14:54:29 -0700
commite1e52eb5a0156839a71c0ffc5424e2160271170e (patch)
treeb4399d8a75489c97fbb3a1d101f55ca65643e764
parenta66dc8a1489d2818b5e63f18e1464be79da1f137 (diff)
downloadrust-e1e52eb5a0156839a71c0ffc5424e2160271170e.tar.gz
rust-e1e52eb5a0156839a71c0ffc5424e2160271170e.zip
Suggest appropriate syntax on missing lifetime specifier in return type
Suggest using `'static` when a lifetime is missing in the return type
with a structured suggestion instead of a note.
-rw-r--r--src/librustc/hir/lowering.rs2
-rw-r--r--src/librustc/middle/resolve_lifetime.rs55
-rw-r--r--src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr6
-rw-r--r--src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr6
-rw-r--r--src/test/ui/foreign-fn-return-lifetime.fixed18
-rw-r--r--src/test/ui/foreign-fn-return-lifetime.rs6
-rw-r--r--src/test/ui/foreign-fn-return-lifetime.stderr10
-rw-r--r--src/test/ui/issues/issue-13497.stderr6
-rw-r--r--src/test/ui/issues/issue-26638.stderr12
-rw-r--r--src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr24
-rw-r--r--src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs10
-rw-r--r--src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr19
-rw-r--r--src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr6
13 files changed, 146 insertions, 34 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index cce872927b1..04a2308cead 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1152,7 +1152,7 @@ impl<'a> LoweringContext<'a> {
             TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
             TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
             TyKind::Rptr(ref region, ref mt) => {
-                let span = t.span.shrink_to_lo();
+                let span = self.sess.source_map().next_point(t.span.shrink_to_lo());
                 let lifetime = match *region {
                     Some(ref lt) => self.lower_lifetime(lt),
                     None => self.elided_ref_lifetime(span),
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 98e80d333c1..86db74b78b9 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -2238,7 +2238,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 
         if let Some(params) = error {
             if lifetime_refs.len() == 1 {
-                self.report_elision_failure(&mut err, params);
+                self.report_elision_failure(&mut err, params, span);
             }
         }
 
@@ -2249,6 +2249,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         &mut self,
         db: &mut DiagnosticBuilder<'_>,
         params: &[ElisionFailureInfo],
+        span: Span,
     ) {
         let mut m = String::new();
         let len = params.len();
@@ -2304,7 +2305,29 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 "this function's return type contains a borrowed value, but \
                  there is no value for it to be borrowed from"
             );
-            help!(db, "consider giving it a 'static lifetime");
+            let msg = "consider giving it a 'static lifetime";
+            match self.tcx.sess.source_map().span_to_snippet(span) {
+                Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability(
+                    span,
+                    msg,
+                    "&'static ".to_owned(),
+                    Applicability::MachineApplicable,
+                ),
+                Ok(ref snippet)
+                if snippet == "'_" => db.span_suggestion_with_applicability(
+                    span,
+                    msg,
+                    "'static".to_owned(),
+                    Applicability::MachineApplicable,
+                ),
+                Ok(ref snippet) => db.span_suggestion_with_applicability(
+                    span,
+                    msg,
+                    format!("{} + 'static", snippet),
+                    Applicability::MaybeIncorrect,
+                ),
+                Err(_) => db.help(msg),
+            };
         } else if elided_len == 0 {
             help!(
                 db,
@@ -2312,11 +2335,29 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                  an elided lifetime, but the lifetime cannot be derived from \
                  the arguments"
             );
-            help!(
-                db,
-                "consider giving it an explicit bounded or 'static \
-                 lifetime"
-            );
+            let msg = "consider giving it an explicit bounded or 'static lifetime";
+            match self.tcx.sess.source_map().span_to_snippet(span) {
+                Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability(
+                    span,
+                    msg,
+                     "&'static ".to_owned(),
+                    Applicability::MachineApplicable,
+                ),
+                Ok(ref snippet)
+                if snippet == "'_" => db.span_suggestion_with_applicability(
+                    span,
+                    msg,
+                    "'static".to_owned(),
+                    Applicability::MachineApplicable,
+                ),
+                Ok(ref snippet) => db.span_suggestion_with_applicability(
+                    span,
+                    msg,
+                    format!("{} + 'static", snippet),
+                    Applicability::MaybeIncorrect,
+                ),
+                Err(_) => db.help(msg),
+            };
         } else if elided_len == 1 {
             help!(
                 db,
diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr
index 0a12aa76a78..4336aaf71ba 100644
--- a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr
+++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr
@@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier
   --> $DIR/bound-lifetime-in-binding-only.rs:62:23
    |
 LL | fn elision<T: Fn() -> &i32>() {
-   |                       ^ expected lifetime parameter
+   |                       ^
+   |                       |
+   |                       expected lifetime parameter
+   |                       help: consider giving it a 'static lifetime: `&'static`
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-   = help: consider giving it a 'static lifetime
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr
index 8fefdfd4d19..fbc4df54225 100644
--- a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr
+++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr
@@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier
   --> $DIR/bound-lifetime-in-return-only.rs:44:23
    |
 LL | fn elision(_: fn() -> &i32) {
-   |                       ^ expected lifetime parameter
+   |                       ^
+   |                       |
+   |                       expected lifetime parameter
+   |                       help: consider giving it a 'static lifetime: `&'static`
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-   = help: consider giving it a 'static lifetime
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/foreign-fn-return-lifetime.fixed b/src/test/ui/foreign-fn-return-lifetime.fixed
new file mode 100644
index 00000000000..9fc35eae705
--- /dev/null
+++ b/src/test/ui/foreign-fn-return-lifetime.fixed
@@ -0,0 +1,18 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-rustfix
+
+extern "C" {
+    pub fn g(_: &u8) -> &u8; // OK
+    pub fn f() -> &'static u8; //~ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/ui/foreign-fn-return-lifetime.rs b/src/test/ui/foreign-fn-return-lifetime.rs
index da77066150c..941e7e05a36 100644
--- a/src/test/ui/foreign-fn-return-lifetime.rs
+++ b/src/test/ui/foreign-fn-return-lifetime.rs
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// run-rustfix
+
 extern "C" {
-    fn g(_: &u8) -> &u8; // OK
-    fn f() -> &u8; //~ ERROR missing lifetime specifier
+    pub fn g(_: &u8) -> &u8; // OK
+    pub fn f() -> &u8; //~ ERROR missing lifetime specifier
 }
 
 fn main() {}
diff --git a/src/test/ui/foreign-fn-return-lifetime.stderr b/src/test/ui/foreign-fn-return-lifetime.stderr
index ea15897b3d6..4e52d6044c4 100644
--- a/src/test/ui/foreign-fn-return-lifetime.stderr
+++ b/src/test/ui/foreign-fn-return-lifetime.stderr
@@ -1,11 +1,13 @@
 error[E0106]: missing lifetime specifier
-  --> $DIR/foreign-fn-return-lifetime.rs:13:15
+  --> $DIR/foreign-fn-return-lifetime.rs:15:19
    |
-LL |     fn f() -> &u8; //~ ERROR missing lifetime specifier
-   |               ^ expected lifetime parameter
+LL |     pub fn f() -> &u8; //~ ERROR missing lifetime specifier
+   |                   ^
+   |                   |
+   |                   expected lifetime parameter
+   |                   help: consider giving it a 'static lifetime: `&'static`
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-   = help: consider giving it a 'static lifetime
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-13497.stderr b/src/test/ui/issues/issue-13497.stderr
index ab6d041bd48..88b6a831d7e 100644
--- a/src/test/ui/issues/issue-13497.stderr
+++ b/src/test/ui/issues/issue-13497.stderr
@@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier
   --> $DIR/issue-13497.rs:12:5
    |
 LL |     &str //~ ERROR missing lifetime specifier
-   |     ^ expected lifetime parameter
+   |     ^
+   |     |
+   |     expected lifetime parameter
+   |     help: consider giving it a 'static lifetime: `&'static`
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-   = help: consider giving it a 'static lifetime
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr
index cf6fcd9f01c..e4464b2dd31 100644
--- a/src/test/ui/issues/issue-26638.stderr
+++ b/src/test/ui/issues/issue-26638.stderr
@@ -10,19 +10,23 @@ error[E0106]: missing lifetime specifier
   --> $DIR/issue-26638.rs:14:40
    |
 LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
-   |                                        ^ expected lifetime parameter
+   |                                        ^
+   |                                        |
+   |                                        expected lifetime parameter
+   |                                        help: consider giving it an explicit bounded or 'static lifetime: `&'static`
    |
    = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
-   = help: consider giving it an explicit bounded or 'static lifetime
 
 error[E0106]: missing lifetime specifier
   --> $DIR/issue-26638.rs:17:22
    |
 LL | fn parse_type_3() -> &str { unimplemented!() }
-   |                      ^ expected lifetime parameter
+   |                      ^
+   |                      |
+   |                      expected lifetime parameter
+   |                      help: consider giving it a 'static lifetime: `&'static`
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-   = help: consider giving it a 'static lifetime
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
index 30cff86ed1d..9962dbc9812 100644
--- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr
@@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:12:11
    |
 LL | fn f() -> &isize {    //~ ERROR missing lifetime specifier
-   |           ^ expected lifetime parameter
+   |           ^
+   |           |
+   |           expected lifetime parameter
+   |           help: consider giving it a 'static lifetime: `&'static`
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-   = help: consider giving it a 'static lifetime
 
 error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:33
@@ -27,28 +29,34 @@ error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:31:20
    |
 LL | fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier
-   |                    ^ expected lifetime parameter
+   |                    ^
+   |                    |
+   |                    expected lifetime parameter
+   |                    help: consider giving it an explicit bounded or 'static lifetime: `&'static`
    |
    = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
-   = help: consider giving it an explicit bounded or 'static lifetime
 
 error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:44:24
    |
 LL | fn j(_x: StaticStr) -> &isize { //~ ERROR missing lifetime specifier
-   |                        ^ expected lifetime parameter
+   |                        ^
+   |                        |
+   |                        expected lifetime parameter
+   |                        help: consider giving it an explicit bounded or 'static lifetime: `&'static`
    |
    = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
-   = help: consider giving it an explicit bounded or 'static lifetime
 
 error[E0106]: missing lifetime specifier
   --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:50:49
    |
 LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize {
-   |                                                 ^ expected lifetime parameter
+   |                                                 ^
+   |                                                 |
+   |                                                 expected lifetime parameter
+   |                                                 help: consider giving it an explicit bounded or 'static lifetime: `&'static`
    |
    = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
-   = help: consider giving it an explicit bounded or 'static lifetime
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs
new file mode 100644
index 00000000000..6b6e263b7fd
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs
@@ -0,0 +1,10 @@
+trait Future {
+    type Item;
+    type Error;
+}
+
+use std::error::Error;
+
+fn foo() -> impl Future<Item=(), Error=Box<Error>> {
+    Ok(())
+}
diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
new file mode 100644
index 00000000000..426941b949d
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
@@ -0,0 +1,19 @@
+error[E0601]: `main` function not found in crate `lifetime_elision_return_type_trait`
+   |
+   = note: consider adding a `main` function to `$DIR/lifetime-elision-return-type-trait.rs`
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/lifetime-elision-return-type-trait.rs:8:44
+   |
+LL | fn foo() -> impl Future<Item=(), Error=Box<Error>> {
+   |                                            ^^^^^
+   |                                            |
+   |                                            expected lifetime parameter
+   |                                            help: consider giving it a 'static lifetime: `Error + 'static`
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0106, E0601.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
index fc9f3e642d4..b0da67a7c34 100644
--- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
+++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
@@ -26,10 +26,12 @@ error[E0106]: missing lifetime specifier
   --> $DIR/underscore-lifetime-binders.rs:24:29
    |
 LL | fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR cannot be used here
-   |                             ^^ expected lifetime parameter
+   |                             ^^
+   |                             |
+   |                             expected lifetime parameter
+   |                             help: consider giving it a 'static lifetime: `'static`
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-   = help: consider giving it a 'static lifetime
 
 error[E0106]: missing lifetime specifier
   --> $DIR/underscore-lifetime-binders.rs:30:35