Skip to content

Commit 91a3172

Browse files
committed
Use spans for input borrowed types unrelated to return type
1 parent 933349e commit 91a3172

12 files changed

+104
-25
lines changed

src/librustc_resolve/lifetimes.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ struct ElisionFailureInfo {
287287
index: usize,
288288
lifetime_count: usize,
289289
have_bound_regions: bool,
290+
span: Span,
290291
}
291292

292293
type ScopeRef<'a> = &'a Scope<'a>;
@@ -2273,6 +2274,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
22732274
index: i,
22742275
lifetime_count: gather.lifetimes.len(),
22752276
have_bound_regions: gather.have_bound_regions,
2277+
span: input.span,
22762278
}
22772279
})
22782280
.collect();
@@ -2483,11 +2485,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
24832485
params.iter().cloned().filter(|info| info.lifetime_count > 0).collect();
24842486

24852487
let elided_len = elided_params.len();
2488+
let mut spans = vec![];
24862489

2487-
// FIXME: collect spans of the input params when appropriate to use in the diagnostic.
24882490
for (i, info) in elided_params.into_iter().enumerate() {
2489-
let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions } = info;
2491+
let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span } = info;
24902492

2493+
spans.push(span);
24912494
let help_name = if let Some(ident) =
24922495
parent.and_then(|body| self.tcx.hir().body(body).params[index].pat.simple_ident())
24932496
{
@@ -2518,31 +2521,39 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
25182521
}
25192522
}
25202523

2524+
let help = |msg| {
2525+
if spans.is_empty() {
2526+
db.help(msg);
2527+
} else {
2528+
db.span_help(spans, msg);
2529+
}
2530+
};
2531+
25212532
if len == 0 {
25222533
db.help(
25232534
"this function's return type contains a borrowed value, \
2524-
but there is no value for it to be borrowed from",
2535+
but there is no value for it to be borrowed from",
25252536
);
25262537
self.suggest_lifetime(db, span, "consider giving it a 'static lifetime")
25272538
} else if elided_len == 0 {
2528-
db.help(
2539+
help(
25292540
"this function's return type contains a borrowed value with \
25302541
an elided lifetime, but the lifetime cannot be derived from \
25312542
the arguments",
25322543
);
25332544
let msg = "consider giving it an explicit bounded or 'static lifetime";
25342545
self.suggest_lifetime(db, span, msg)
25352546
} else if elided_len == 1 {
2536-
db.help(&format!(
2547+
help(&format!(
25372548
"this function's return type contains a borrowed value, \
2538-
but the signature does not say which {} it is borrowed from",
2549+
but the signature does not say which {} it is borrowed from",
25392550
m
25402551
));
25412552
true
25422553
} else {
2543-
db.help(&format!(
2554+
help(&format!(
25442555
"this function's return type contains a borrowed value, \
2545-
but the signature does not say whether it is borrowed from {}",
2556+
but the signature does not say whether it is borrowed from {}",
25462557
m
25472558
));
25482559
true

src/test/ui/async-await/issues/issue-63388-2.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ error[E0106]: missing lifetime specifier
44
LL | ) -> &dyn Foo
55
| ^ help: consider using the named lifetime: `&'a`
66
|
7-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar`
7+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar`
8+
--> $DIR/issue-63388-2.rs:11:14
9+
|
10+
LL | foo: &dyn Foo, bar: &'a dyn Foo
11+
| ^^^^^^^^ ^^^^^^^^^^^
812

913
error: cannot infer an appropriate lifetime
1014
--> $DIR/issue-63388-2.rs:11:9

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ error[E0106]: missing lifetime specifier
44
LL | type Foo = fn(&u8, &u8) -> &u8;
55
| ^ expected named lifetime parameter
66
|
7-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
7+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
8+
--> $DIR/issue-19707.rs:3:15
9+
|
10+
LL | type Foo = fn(&u8, &u8) -> &u8;
11+
| ^^^ ^^^
812
help: consider introducing a named lifetime parameter
913
|
1014
LL | type Foo<'lifetime> = fn(&u8, &u8) -> &'lifetime u8;
@@ -16,7 +20,11 @@ error[E0106]: missing lifetime specifier
1620
LL | fn bar<F: Fn(&u8, &u8) -> &u8>(f: &F) {}
1721
| ^ expected named lifetime parameter
1822
|
19-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
23+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
24+
--> $DIR/issue-19707.rs:5:14
25+
|
26+
LL | fn bar<F: Fn(&u8, &u8) -> &u8>(f: &F) {}
27+
| ^^^ ^^^
2028
= note: for more information on Higher-Ranked lifetimes, visit https://doc.rust-lang.org/nomicon/hrtb.html
2129
help: consider introducing a Higher-Ranked lifetime
2230
|

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ error[E0106]: missing lifetime specifier
44
LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
55
| ^ expected named lifetime parameter
66
|
7-
= help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
7+
help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
8+
--> $DIR/issue-26638.rs:1:21
9+
|
10+
LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
812
help: consider introducing a named lifetime parameter
913
|
1014
LL | fn parse_type<'lifetime>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'lifetime str { iter.next() }

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

+15-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ error[E0106]: missing lifetime specifier
44
LL | fn f(a: &S, b: i32) -> &i32 {
55
| ^ expected named lifetime parameter
66
|
7-
= help: this function's return type contains a borrowed value, but the signature does not say which one of `a`'s 2 lifetimes it is borrowed from
7+
help: this function's return type contains a borrowed value, but the signature does not say which one of `a`'s 2 lifetimes it is borrowed from
8+
--> $DIR/issue-30255.rs:9:9
9+
|
10+
LL | fn f(a: &S, b: i32) -> &i32 {
11+
| ^^
812
help: consider introducing a named lifetime parameter
913
|
1014
LL | fn f<'lifetime>(a: &S, b: i32) -> &'lifetime i32 {
@@ -16,7 +20,11 @@ error[E0106]: missing lifetime specifier
1620
LL | fn g(a: &S, b: bool, c: &i32) -> &i32 {
1721
| ^ expected named lifetime parameter
1822
|
19-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c`
23+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c`
24+
--> $DIR/issue-30255.rs:14:9
25+
|
26+
LL | fn g(a: &S, b: bool, c: &i32) -> &i32 {
27+
| ^^ ^^^^
2028
help: consider introducing a named lifetime parameter
2129
|
2230
LL | fn g<'lifetime>(a: &S, b: bool, c: &i32) -> &'lifetime i32 {
@@ -28,7 +36,11 @@ error[E0106]: missing lifetime specifier
2836
LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 {
2937
| ^ expected named lifetime parameter
3038
|
31-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d`
39+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d`
40+
--> $DIR/issue-30255.rs:19:9
41+
|
42+
LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 {
43+
| ^^^^^ ^^ ^^^^
3244
help: consider introducing a named lifetime parameter
3345
|
3446
LL | fn h<'lifetime>(a: &bool, b: bool, c: &S, d: &i32) -> &'lifetime i32 {

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ error[E0106]: missing lifetime specifier
1212
LL | fn g(_x: &isize, _y: &isize) -> &isize {
1313
| ^ expected named lifetime parameter
1414
|
15-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_x` or `_y`
15+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_x` or `_y`
16+
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:10
17+
|
18+
LL | fn g(_x: &isize, _y: &isize) -> &isize {
19+
| ^^^^^^ ^^^^^^
1620
help: consider introducing a named lifetime parameter
1721
|
1822
LL | fn g<'lifetime>(_x: &isize, _y: &isize) -> &'lifetime isize {
@@ -24,7 +28,11 @@ error[E0106]: missing lifetime specifier
2428
LL | fn h(_x: &Foo) -> &isize {
2529
| ^ expected named lifetime parameter
2630
|
27-
= help: this function's return type contains a borrowed value, but the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from
31+
help: this function's return type contains a borrowed value, but the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from
32+
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:10
33+
|
34+
LL | fn h(_x: &Foo) -> &isize {
35+
| ^^^^
2836
help: consider introducing a named lifetime parameter
2937
|
3038
LL | fn h<'lifetime>(_x: &Foo) -> &'lifetime isize {

src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ error[E0106]: missing lifetime specifier
44
LL | fn foo(x: &i32, y: &i32) -> &i32 {
55
| ^ expected named lifetime parameter
66
|
7-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
7+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
8+
--> $DIR/ex1b-return-no-names-if-else.rs:1:11
9+
|
10+
LL | fn foo(x: &i32, y: &i32) -> &i32 {
11+
| ^^^^ ^^^^
812
help: consider introducing a named lifetime parameter
913
|
1014
LL | fn foo<'lifetime>(x: &i32, y: &i32) -> &'lifetime i32 {

src/test/ui/rfc1623.stderr

+10-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,23 @@ error[E0106]: missing lifetime specifier
44
LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
55
| ^ expected named lifetime parameter
66
|
7-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
7+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
8+
--> $DIR/rfc1623.rs:8:29
9+
|
10+
LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
11+
| ^^^ ^^^
812

913
error[E0106]: missing lifetime specifier
1014
--> $DIR/rfc1623.rs:10:39
1115
|
1216
LL | &(non_elidable as fn(&u8, &u8) -> &u8);
1317
| ^ expected named lifetime parameter
1418
|
15-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
19+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
20+
--> $DIR/rfc1623.rs:10:26
21+
|
22+
LL | &(non_elidable as fn(&u8, &u8) -> &u8);
23+
| ^^^ ^^^
1624

1725
error: aborting due to 2 previous errors
1826

src/test/ui/suggestions/return-without-lifetime.stderr

+10-2
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,23 @@ error[E0106]: missing lifetime specifier
1010
LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
1111
| ^ help: consider using the named lifetime: `&'a`
1212
|
13-
= 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
13+
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
14+
--> $DIR/return-without-lifetime.rs:5:20
15+
|
16+
LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() }
17+
| ^^^^^^^^^
1418

1519
error[E0106]: missing lifetime specifier
1620
--> $DIR/return-without-lifetime.rs:7:35
1721
|
1822
LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
1923
| ^ help: consider using the named lifetime: `&'a`
2024
|
21-
= 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
25+
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
26+
--> $DIR/return-without-lifetime.rs:7:20
27+
|
28+
LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() }
29+
| ^^^^^^^^^^
2230

2331
error: aborting due to 3 previous errors
2432

src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ error[E0106]: missing lifetime specifier
44
LL | let _: dyn Foo(&isize, &usize) -> &usize;
55
| ^ expected named lifetime parameter
66
|
7-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
7+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
8+
--> $DIR/unboxed-closure-sugar-lifetime-elision.rs:26:20
9+
|
10+
LL | let _: dyn Foo(&isize, &usize) -> &usize;
11+
| ^^^^^^ ^^^^^^
812
help: consider introducing a named lifetime parameter
913
|
1014
LL | fn main<'lifetime>() {

src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ error[E0106]: missing lifetime specifier
44
LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } }
55
| ^^ expected named lifetime parameter
66
|
7-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
7+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
8+
--> $DIR/in-fn-return-illegal.rs:5:11
9+
|
10+
LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } }
11+
| ^^^^ ^^^^
812
help: consider introducing a named lifetime parameter
913
|
1014
LL | fn foo<'lifetime>(x: &u32, y: &u32) -> &'lifetime u32 { loop { } }

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ error[E0106]: missing lifetime specifier
3030
LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y }
3131
| ^^ expected named lifetime parameter
3232
|
33-
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y`
33+
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y`
34+
--> $DIR/underscore-lifetime-binders.rs:16:12
35+
|
36+
LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y }
37+
| ^^^^^^ ^^^^^^
3438
help: consider introducing a named lifetime parameter
3539
|
3640
LL | fn foo2<'lifetime>(_: &'_ u8, y: &'_ u8) -> &'lifetime u8 { y }

0 commit comments

Comments
 (0)