Skip to content

Commit 47aabb3

Browse files
committed
polish invisible-lifetimes lint: terminal-legibility and macro tolerance
• The "indicate the anonymous lifetime: `'_,`" span label seemed at risk of being hard to read, even if it's not wrong. When we're splicing the anonymous lifetime into an already-existing set of angle-brackets like this, it's probably better to show the entire expression. • By using the path span instead of that of its final segment, we can (very) slightly simplify our code (by the amount of one less local variable), and handle at least some macro scenarios correctly (see `autowrapper!` in the UI test, which is a run-rustfix test)! • Another macro scenario (in type-annotation position) is observed to work. This remains part of the grand endeavor of issue no. 52041!
1 parent 7c4e9d4 commit 47aabb3

File tree

4 files changed

+96
-10
lines changed

4 files changed

+96
-10
lines changed

src/librustc/middle/resolve_lifetime.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,16 +2109,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
21092109
);
21102110

21112111
if implicit_lifetimes.len() == 1 {
2112-
let segment_span = &path.segments[path.segments.len()-1].ident.span;
21132112
let (replace_span,
21142113
suggestion) = if generic_args.args.len() == implicit_lifetimes.len() &&
21152114
generic_args.bindings.is_empty() {
21162115
// If there are no (non-implicit) generic args or bindings, our
21172116
// suggestion includes the angle brackets
2118-
(segment_span.shrink_to_hi(), "<'_>")
2117+
(path.span.shrink_to_hi(), "<'_>".to_owned())
21192118
} else {
21202119
// Otherwise—sorry, this is kind of gross—we need to infer the
2121-
// replacement point span from the generics that do exist
2120+
// place to splice in `'_, ` from the generics that do exist
21222121
let mut first_generic_span = None;
21232122
for ref arg in &generic_args.args {
21242123
match arg {
@@ -2143,9 +2142,18 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
21432142
break;
21442143
}
21452144
}
2146-
let replace_span = first_generic_span
2145+
let first_generic_span = first_generic_span
21472146
.expect("checked earlier that non-implicit args or bindings exist");
2148-
(replace_span.shrink_to_lo(), "'_, ")
2147+
// If our codemap can be trusted, construct the entire `Path<'_, T>` source
2148+
// suggestion
2149+
if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(path.span) {
2150+
let (before, after) = snippet.split_at(
2151+
(first_generic_span.lo().0 - path.span.lo().0) as usize
2152+
);
2153+
(path.span, format!("{}{}{}", before, "'_, ", after))
2154+
} else {
2155+
(first_generic_span.shrink_to_lo(), "'_, ".to_owned())
2156+
}
21492157
};
21502158
err.span_suggestion_with_applicability(
21512159
replace_span,

src/test/ui/in-band-lifetimes/elided-lifetimes.fixed

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,41 @@ fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow<'_> {
4646
WrappedWithBow { gift }
4747
}
4848

49+
macro_rules! autowrapper {
50+
($type_name:ident, $fn_name:ident, $lt:lifetime) => {
51+
struct $type_name<$lt> {
52+
gift: &$lt str
53+
}
54+
55+
fn $fn_name(gift: &str) -> $type_name<'_> {
56+
//~^ ERROR implicit lifetime parameters in types are deprecated
57+
//~| HELP indicate the anonymous lifetime
58+
$type_name { gift }
59+
}
60+
}
61+
}
62+
63+
autowrapper!(Autowrapped, autowrap_gift, 'a);
64+
//~^ NOTE in this expansion of autowrapper!
65+
//~| NOTE in this expansion of autowrapper!
66+
67+
macro_rules! anytuple_ref_ty {
68+
($($types:ty),*) => {
69+
Ref<'_, ($($types),*)>
70+
//~^ ERROR implicit lifetime parameters in types are deprecated
71+
//~| HELP indicate the anonymous lifetime
72+
}
73+
}
74+
4975
fn main() {
5076
let honesty = RefCell::new((4, 'e'));
5177
let loyalty: Ref<'_, (u32, char)> = honesty.borrow();
5278
//~^ ERROR implicit lifetime parameters in types are deprecated
5379
//~| HELP indicate the anonymous lifetime
5480
let generosity = Ref::map(loyalty, |t| &t.0);
81+
82+
let laughter = RefCell::new((true, "magic"));
83+
let yellow: anytuple_ref_ty!(bool, &str) = laughter.borrow();
84+
//~^ NOTE in this expansion of anytuple_ref_ty!
85+
//~| NOTE in this expansion of anytuple_ref_ty!
5586
}

src/test/ui/in-band-lifetimes/elided-lifetimes.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,41 @@ fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow {
4646
WrappedWithBow { gift }
4747
}
4848

49+
macro_rules! autowrapper {
50+
($type_name:ident, $fn_name:ident, $lt:lifetime) => {
51+
struct $type_name<$lt> {
52+
gift: &$lt str
53+
}
54+
55+
fn $fn_name(gift: &str) -> $type_name {
56+
//~^ ERROR implicit lifetime parameters in types are deprecated
57+
//~| HELP indicate the anonymous lifetime
58+
$type_name { gift }
59+
}
60+
}
61+
}
62+
63+
autowrapper!(Autowrapped, autowrap_gift, 'a);
64+
//~^ NOTE in this expansion of autowrapper!
65+
//~| NOTE in this expansion of autowrapper!
66+
67+
macro_rules! anytuple_ref_ty {
68+
($($types:ty),*) => {
69+
Ref<($($types),*)>
70+
//~^ ERROR implicit lifetime parameters in types are deprecated
71+
//~| HELP indicate the anonymous lifetime
72+
}
73+
}
74+
4975
fn main() {
5076
let honesty = RefCell::new((4, 'e'));
5177
let loyalty: Ref<(u32, char)> = honesty.borrow();
5278
//~^ ERROR implicit lifetime parameters in types are deprecated
5379
//~| HELP indicate the anonymous lifetime
5480
let generosity = Ref::map(loyalty, |t| &t.0);
81+
82+
let laughter = RefCell::new((true, "magic"));
83+
let yellow: anytuple_ref_ty!(bool, &str) = laughter.borrow();
84+
//~^ NOTE in this expansion of anytuple_ref_ty!
85+
//~| NOTE in this expansion of anytuple_ref_ty!
5586
}

src/test/ui/in-band-lifetimes/elided-lifetimes.stderr

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,28 @@ LL | fn wrap_gift_with_bow(gift: &str) -> WrappedWithBow {
2323
| ^^^^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
2424

2525
error: implicit lifetime parameters in types are deprecated
26-
--> $DIR/elided-lifetimes.rs:51:18
26+
--> $DIR/elided-lifetimes.rs:77:18
2727
|
2828
LL | let loyalty: Ref<(u32, char)> = honesty.borrow();
29-
| ^^^^-^^^^^^^^^^^
30-
| |
31-
| help: indicate the anonymous lifetime: `'_,`
29+
| ^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Ref<'_, (u32, char)>`
3230

33-
error: aborting due to 4 previous errors
31+
error: implicit lifetime parameters in types are deprecated
32+
--> $DIR/elided-lifetimes.rs:69:9
33+
|
34+
LL | Ref<($($types),*)>
35+
| ^^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Ref<'_, ($($types),*)>`
36+
...
37+
LL | let yellow: anytuple_ref_ty!(bool, &str) = laughter.borrow();
38+
| ---------------------------- in this macro invocation
39+
40+
error: implicit lifetime parameters in types are deprecated
41+
--> $DIR/elided-lifetimes.rs:55:36
42+
|
43+
LL | fn $fn_name(gift: &str) -> $type_name {
44+
| ^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
45+
...
46+
LL | autowrapper!(Autowrapped, autowrap_gift, 'a);
47+
| --------------------------------------------- in this macro invocation
48+
49+
error: aborting due to 6 previous errors
3450

0 commit comments

Comments
 (0)