Skip to content

Commit e1e52eb

Browse files
committed
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.
1 parent a66dc8a commit e1e52eb

13 files changed

+146
-34
lines changed

src/librustc/hir/lowering.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ impl<'a> LoweringContext<'a> {
11521152
TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
11531153
TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
11541154
TyKind::Rptr(ref region, ref mt) => {
1155-
let span = t.span.shrink_to_lo();
1155+
let span = self.sess.source_map().next_point(t.span.shrink_to_lo());
11561156
let lifetime = match *region {
11571157
Some(ref lt) => self.lower_lifetime(lt),
11581158
None => self.elided_ref_lifetime(span),

src/librustc/middle/resolve_lifetime.rs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2238,7 +2238,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
22382238

22392239
if let Some(params) = error {
22402240
if lifetime_refs.len() == 1 {
2241-
self.report_elision_failure(&mut err, params);
2241+
self.report_elision_failure(&mut err, params, span);
22422242
}
22432243
}
22442244

@@ -2249,6 +2249,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
22492249
&mut self,
22502250
db: &mut DiagnosticBuilder<'_>,
22512251
params: &[ElisionFailureInfo],
2252+
span: Span,
22522253
) {
22532254
let mut m = String::new();
22542255
let len = params.len();
@@ -2304,19 +2305,59 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
23042305
"this function's return type contains a borrowed value, but \
23052306
there is no value for it to be borrowed from"
23062307
);
2307-
help!(db, "consider giving it a 'static lifetime");
2308+
let msg = "consider giving it a 'static lifetime";
2309+
match self.tcx.sess.source_map().span_to_snippet(span) {
2310+
Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability(
2311+
span,
2312+
msg,
2313+
"&'static ".to_owned(),
2314+
Applicability::MachineApplicable,
2315+
),
2316+
Ok(ref snippet)
2317+
if snippet == "'_" => db.span_suggestion_with_applicability(
2318+
span,
2319+
msg,
2320+
"'static".to_owned(),
2321+
Applicability::MachineApplicable,
2322+
),
2323+
Ok(ref snippet) => db.span_suggestion_with_applicability(
2324+
span,
2325+
msg,
2326+
format!("{} + 'static", snippet),
2327+
Applicability::MaybeIncorrect,
2328+
),
2329+
Err(_) => db.help(msg),
2330+
};
23082331
} else if elided_len == 0 {
23092332
help!(
23102333
db,
23112334
"this function's return type contains a borrowed value with \
23122335
an elided lifetime, but the lifetime cannot be derived from \
23132336
the arguments"
23142337
);
2315-
help!(
2316-
db,
2317-
"consider giving it an explicit bounded or 'static \
2318-
lifetime"
2319-
);
2338+
let msg = "consider giving it an explicit bounded or 'static lifetime";
2339+
match self.tcx.sess.source_map().span_to_snippet(span) {
2340+
Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability(
2341+
span,
2342+
msg,
2343+
"&'static ".to_owned(),
2344+
Applicability::MachineApplicable,
2345+
),
2346+
Ok(ref snippet)
2347+
if snippet == "'_" => db.span_suggestion_with_applicability(
2348+
span,
2349+
msg,
2350+
"'static".to_owned(),
2351+
Applicability::MachineApplicable,
2352+
),
2353+
Ok(ref snippet) => db.span_suggestion_with_applicability(
2354+
span,
2355+
msg,
2356+
format!("{} + 'static", snippet),
2357+
Applicability::MaybeIncorrect,
2358+
),
2359+
Err(_) => db.help(msg),
2360+
};
23202361
} else if elided_len == 1 {
23212362
help!(
23222363
db,

src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier
22
--> $DIR/bound-lifetime-in-binding-only.rs:62:23
33
|
44
LL | fn elision<T: Fn() -> &i32>() {
5-
| ^ expected lifetime parameter
5+
| ^
6+
| |
7+
| expected lifetime parameter
8+
| help: consider giving it a 'static lifetime: `&'static`
69
|
710
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
8-
= help: consider giving it a 'static lifetime
911

1012
error: aborting due to previous error
1113

src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier
22
--> $DIR/bound-lifetime-in-return-only.rs:44:23
33
|
44
LL | fn elision(_: fn() -> &i32) {
5-
| ^ expected lifetime parameter
5+
| ^
6+
| |
7+
| expected lifetime parameter
8+
| help: consider giving it a 'static lifetime: `&'static`
69
|
710
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
8-
= help: consider giving it a 'static lifetime
911

1012
error: aborting due to previous error
1113

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// run-rustfix
12+
13+
extern "C" {
14+
pub fn g(_: &u8) -> &u8; // OK
15+
pub fn f() -> &'static u8; //~ ERROR missing lifetime specifier
16+
}
17+
18+
fn main() {}

src/test/ui/foreign-fn-return-lifetime.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// run-rustfix
12+
1113
extern "C" {
12-
fn g(_: &u8) -> &u8; // OK
13-
fn f() -> &u8; //~ ERROR missing lifetime specifier
14+
pub fn g(_: &u8) -> &u8; // OK
15+
pub fn f() -> &u8; //~ ERROR missing lifetime specifier
1416
}
1517

1618
fn main() {}

src/test/ui/foreign-fn-return-lifetime.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
error[E0106]: missing lifetime specifier
2-
--> $DIR/foreign-fn-return-lifetime.rs:13:15
2+
--> $DIR/foreign-fn-return-lifetime.rs:15:19
33
|
4-
LL | fn f() -> &u8; //~ ERROR missing lifetime specifier
5-
| ^ expected lifetime parameter
4+
LL | pub fn f() -> &u8; //~ ERROR missing lifetime specifier
5+
| ^
6+
| |
7+
| expected lifetime parameter
8+
| help: consider giving it a 'static lifetime: `&'static`
69
|
710
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
8-
= help: consider giving it a 'static lifetime
911

1012
error: aborting due to previous error
1113

src/test/ui/issues/issue-13497.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier
22
--> $DIR/issue-13497.rs:12:5
33
|
44
LL | &str //~ ERROR missing lifetime specifier
5-
| ^ expected lifetime parameter
5+
| ^
6+
| |
7+
| expected lifetime parameter
8+
| help: consider giving it a 'static lifetime: `&'static`
69
|
710
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
8-
= help: consider giving it a 'static lifetime
911

1012
error: aborting due to previous error
1113

src/test/ui/issues/issue-26638.stderr

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,23 @@ error[E0106]: missing lifetime specifier
1010
--> $DIR/issue-26638.rs:14:40
1111
|
1212
LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
13-
| ^ expected lifetime parameter
13+
| ^
14+
| |
15+
| expected lifetime parameter
16+
| help: consider giving it an explicit bounded or 'static lifetime: `&'static`
1417
|
1518
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
16-
= help: consider giving it an explicit bounded or 'static lifetime
1719

1820
error[E0106]: missing lifetime specifier
1921
--> $DIR/issue-26638.rs:17:22
2022
|
2123
LL | fn parse_type_3() -> &str { unimplemented!() }
22-
| ^ expected lifetime parameter
24+
| ^
25+
| |
26+
| expected lifetime parameter
27+
| help: consider giving it a 'static lifetime: `&'static`
2328
|
2429
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
25-
= help: consider giving it a 'static lifetime
2630

2731
error: aborting due to 3 previous errors
2832

src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier
22
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:12:11
33
|
44
LL | fn f() -> &isize { //~ ERROR missing lifetime specifier
5-
| ^ expected lifetime parameter
5+
| ^
6+
| |
7+
| expected lifetime parameter
8+
| help: consider giving it a 'static lifetime: `&'static`
69
|
710
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
8-
= help: consider giving it a 'static lifetime
911

1012
error[E0106]: missing lifetime specifier
1113
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:33
@@ -27,28 +29,34 @@ error[E0106]: missing lifetime specifier
2729
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:31:20
2830
|
2931
LL | fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier
30-
| ^ expected lifetime parameter
32+
| ^
33+
| |
34+
| expected lifetime parameter
35+
| help: consider giving it an explicit bounded or 'static lifetime: `&'static`
3136
|
3237
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
33-
= help: consider giving it an explicit bounded or 'static lifetime
3438

3539
error[E0106]: missing lifetime specifier
3640
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:44:24
3741
|
3842
LL | fn j(_x: StaticStr) -> &isize { //~ ERROR missing lifetime specifier
39-
| ^ expected lifetime parameter
43+
| ^
44+
| |
45+
| expected lifetime parameter
46+
| help: consider giving it an explicit bounded or 'static lifetime: `&'static`
4047
|
4148
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
42-
= help: consider giving it an explicit bounded or 'static lifetime
4349

4450
error[E0106]: missing lifetime specifier
4551
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:50:49
4652
|
4753
LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize {
48-
| ^ expected lifetime parameter
54+
| ^
55+
| |
56+
| expected lifetime parameter
57+
| help: consider giving it an explicit bounded or 'static lifetime: `&'static`
4958
|
5059
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
51-
= help: consider giving it an explicit bounded or 'static lifetime
5260

5361
error: aborting due to 6 previous errors
5462

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
trait Future {
2+
type Item;
3+
type Error;
4+
}
5+
6+
use std::error::Error;
7+
8+
fn foo() -> impl Future<Item=(), Error=Box<Error>> {
9+
Ok(())
10+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0601]: `main` function not found in crate `lifetime_elision_return_type_trait`
2+
|
3+
= note: consider adding a `main` function to `$DIR/lifetime-elision-return-type-trait.rs`
4+
5+
error[E0106]: missing lifetime specifier
6+
--> $DIR/lifetime-elision-return-type-trait.rs:8:44
7+
|
8+
LL | fn foo() -> impl Future<Item=(), Error=Box<Error>> {
9+
| ^^^^^
10+
| |
11+
| expected lifetime parameter
12+
| help: consider giving it a 'static lifetime: `Error + 'static`
13+
|
14+
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
15+
16+
error: aborting due to 2 previous errors
17+
18+
Some errors occurred: E0106, E0601.
19+
For more information about an error, try `rustc --explain E0106`.

src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ error[E0106]: missing lifetime specifier
2626
--> $DIR/underscore-lifetime-binders.rs:24:29
2727
|
2828
LL | fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR cannot be used here
29-
| ^^ expected lifetime parameter
29+
| ^^
30+
| |
31+
| expected lifetime parameter
32+
| help: consider giving it a 'static lifetime: `'static`
3033
|
3134
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
32-
= help: consider giving it a 'static lifetime
3335

3436
error[E0106]: missing lifetime specifier
3537
--> $DIR/underscore-lifetime-binders.rs:30:35

0 commit comments

Comments
 (0)