Skip to content

Commit 795d307

Browse files
committed
Suggest return lifetime when there's only one named lifetime
1 parent 7486b9c commit 795d307

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

src/librustc/middle/resolve_lifetime.rs

+33-4
Original file line numberDiff line numberDiff line change
@@ -2298,6 +2298,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
22982298
let span = lifetime_refs[0].span;
22992299
let mut late_depth = 0;
23002300
let mut scope = self.scope;
2301+
let mut lifetime_names = FxHashSet::default();
23012302
let error = loop {
23022303
match *scope {
23032304
// Do not assign any resolution, it will be inferred.
@@ -2310,7 +2311,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
23102311
scope = s;
23112312
}
23122313

2313-
Scope::Elision { ref elide, .. } => {
2314+
Scope::Elision { ref elide, ref s, .. } => {
23142315
let lifetime = match *elide {
23152316
Elide::FreshLateAnon(ref counter) => {
23162317
for lifetime_ref in lifetime_refs {
@@ -2320,7 +2321,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
23202321
return;
23212322
}
23222323
Elide::Exact(l) => l.shifted(late_depth),
2323-
Elide::Error(ref e) => break Some(e),
2324+
Elide::Error(ref e) => {
2325+
if let Scope::Binder { ref lifetimes, .. } = s {
2326+
for name in lifetimes.keys() {
2327+
if let hir::ParamName::Plain(name) = name {
2328+
lifetime_names.insert(*name);
2329+
}
2330+
}
2331+
}
2332+
break Some(e);
2333+
}
23242334
};
23252335
for lifetime_ref in lifetime_refs {
23262336
self.insert_lifetime(lifetime_ref, lifetime);
@@ -2343,7 +2353,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
23432353
}
23442354
}
23452355
if add_label {
2346-
add_missing_lifetime_specifiers_label(&mut err, span, lifetime_refs.len());
2356+
add_missing_lifetime_specifiers_label(
2357+
&mut err,
2358+
span,
2359+
lifetime_refs.len(),
2360+
&lifetime_names,
2361+
self.tcx.sess.source_map().span_to_snippet(span).ok().as_ref().map(|s| s.as_str()),
2362+
);
23472363
}
23482364

23492365
err.emit();
@@ -2884,10 +2900,23 @@ fn add_missing_lifetime_specifiers_label(
28842900
err: &mut DiagnosticBuilder<'_>,
28852901
span: Span,
28862902
count: usize,
2903+
lifetime_names: &FxHashSet<ast::Ident>,
2904+
snippet: Option<&str>,
28872905
) {
28882906
if count > 1 {
28892907
err.span_label(span, format!("expected {} lifetime parameters", count));
2908+
} else if let (1, Some(name), Some("&")) = (
2909+
lifetime_names.len(),
2910+
lifetime_names.iter().next(),
2911+
snippet,
2912+
) {
2913+
err.span_suggestion(
2914+
span,
2915+
&format!("consider using the named lifetime `{}`", name),
2916+
format!("&{} ", name),
2917+
Applicability::MaybeIncorrect,
2918+
);
28902919
} else {
28912920
err.span_label(span, "expected lifetime parameter");
2892-
};
2921+
}
28932922
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
struct Thing<'a>(&'a ());
2+
3+
fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
4+
//~^ ERROR missing lifetime specifier
5+
fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
6+
//~^ ERROR missing lifetime specifier
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/return-without-lifetime.rs:3:34
3+
|
4+
LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
5+
| ^ help: consider using the named lifetime `'a`: `&'a`
6+
|
7+
= help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
8+
9+
error[E0106]: missing lifetime specifier
10+
--> $DIR/return-without-lifetime.rs:5:35
11+
|
12+
LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
13+
| ^ help: consider using the named lifetime `'a`: `&'a`
14+
|
15+
= help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0106`.

0 commit comments

Comments
 (0)