Skip to content

Commit 8a830cf

Browse files
Rollup merge of rust-lang#106935 - TaKO8Ki:fix-104440, r=cjgillot
Fix `SingleUseLifetime` ICE Fixes rust-lang#104440 cc: ``@matthiaskrgr``
2 parents 5645d10 + fe96c11 commit 8a830cf

File tree

5 files changed

+174
-25
lines changed

5 files changed

+174
-25
lines changed

compiler/rustc_lint/src/context.rs

+26-21
Original file line numberDiff line numberDiff line change
@@ -825,34 +825,39 @@ pub trait LintContext: Sized {
825825
debug!(?param_span, ?use_span, ?deletion_span);
826826
db.span_label(param_span, "this lifetime...");
827827
db.span_label(use_span, "...is used only here");
828-
let msg = "elide the single-use lifetime";
829-
let (use_span, replace_lt) = if elide {
830-
let use_span = sess.source_map().span_extend_while(
831-
use_span,
832-
char::is_whitespace,
833-
).unwrap_or(use_span);
834-
(use_span, String::new())
835-
} else {
836-
(use_span, "'_".to_owned())
837-
};
838-
db.multipart_suggestion(
839-
msg,
840-
vec![(deletion_span, String::new()), (use_span, replace_lt)],
841-
Applicability::MachineApplicable,
842-
);
828+
if let Some(deletion_span) = deletion_span {
829+
let msg = "elide the single-use lifetime";
830+
let (use_span, replace_lt) = if elide {
831+
let use_span = sess.source_map().span_extend_while(
832+
use_span,
833+
char::is_whitespace,
834+
).unwrap_or(use_span);
835+
(use_span, String::new())
836+
} else {
837+
(use_span, "'_".to_owned())
838+
};
839+
debug!(?deletion_span, ?use_span);
840+
db.multipart_suggestion(
841+
msg,
842+
vec![(deletion_span, String::new()), (use_span, replace_lt)],
843+
Applicability::MachineApplicable,
844+
);
845+
}
843846
},
844847
BuiltinLintDiagnostics::SingleUseLifetime {
845848
param_span: _,
846849
use_span: None,
847850
deletion_span,
848851
} => {
849852
debug!(?deletion_span);
850-
db.span_suggestion(
851-
deletion_span,
852-
"elide the unused lifetime",
853-
"",
854-
Applicability::MachineApplicable,
855-
);
853+
if let Some(deletion_span) = deletion_span {
854+
db.span_suggestion(
855+
deletion_span,
856+
"elide the unused lifetime",
857+
"",
858+
Applicability::MachineApplicable,
859+
);
860+
}
856861
},
857862
BuiltinLintDiagnostics::NamedArgumentUsedPositionally{ position_sp_to_replace, position_sp_for_msg, named_arg_sp, named_arg_name, is_formatting_arg} => {
858863
db.span_label(named_arg_sp, "this named argument is referred to by position in formatting string");

compiler/rustc_lint_defs/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ pub enum BuiltinLintDiagnostics {
503503
param_span: Span,
504504
/// Span of the code that should be removed when eliding this lifetime.
505505
/// This span should include leading or trailing comma.
506-
deletion_span: Span,
506+
deletion_span: Option<Span>,
507507
/// Span of the single use, or None if the lifetime is never used.
508508
/// If true, the lifetime will be fully elided.
509509
use_span: Option<(Span, bool)>,

compiler/rustc_resolve/src/late/diagnostics.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -2188,15 +2188,31 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
21882188
let deletion_span = || {
21892189
if params.len() == 1 {
21902190
// if sole lifetime, remove the entire `<>` brackets
2191-
generics_span
2191+
Some(generics_span)
21922192
} else if param_index == 0 {
21932193
// if removing within `<>` brackets, we also want to
21942194
// delete a leading or trailing comma as appropriate
2195-
param.span().to(params[param_index + 1].span().shrink_to_lo())
2195+
match (
2196+
param.span().find_ancestor_inside(generics_span),
2197+
params[param_index + 1].span().find_ancestor_inside(generics_span),
2198+
) {
2199+
(Some(param_span), Some(next_param_span)) => {
2200+
Some(param_span.to(next_param_span.shrink_to_lo()))
2201+
}
2202+
_ => None,
2203+
}
21962204
} else {
21972205
// if removing within `<>` brackets, we also want to
21982206
// delete a leading or trailing comma as appropriate
2199-
params[param_index - 1].span().shrink_to_hi().to(param.span())
2207+
match (
2208+
param.span().find_ancestor_inside(generics_span),
2209+
params[param_index - 1].span().find_ancestor_inside(generics_span),
2210+
) {
2211+
(Some(param_span), Some(prev_param_span)) => {
2212+
Some(prev_param_span.shrink_to_hi().to(param_span))
2213+
}
2214+
_ => None,
2215+
}
22002216
}
22012217
};
22022218
match use_set {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#![feature(decl_macro, rustc_attrs)]
2+
#![deny(single_use_lifetimes)]
3+
4+
mod type_params {
5+
macro m($T:ident) {
6+
fn f<$T: Clone, T: PartialEq>(t1: $T, t2: T) -> ($T, bool) {
7+
(t1.clone(), t2 == t2)
8+
}
9+
}
10+
11+
#[rustc_macro_transparency = "semitransparent"]
12+
macro n($T:ident) {
13+
fn g<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
14+
(t1.clone(), t2.clone())
15+
}
16+
fn h<T: Clone>(t1: $T, t2: T) -> (T, $T) {
17+
(t1.clone(), t2.clone())
18+
}
19+
}
20+
21+
#[rustc_macro_transparency = "transparent"]
22+
macro p($T:ident) {
23+
fn j<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
24+
(t1.clone(), t2.clone())
25+
}
26+
fn k<T: Clone>(t1: $T, t2: T) -> (T, $T) {
27+
(t1.clone(), t2.clone())
28+
}
29+
}
30+
31+
m!(T);
32+
n!(T);
33+
p!(T);
34+
}
35+
36+
mod lifetime_params {
37+
macro m($a:lifetime) {
38+
fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) { //~ ERROR lifetime parameter `'a` only used once
39+
(t1, t2)
40+
}
41+
}
42+
43+
#[rustc_macro_transparency = "semitransparent"]
44+
macro n($a:lifetime) {
45+
fn g<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
46+
(t1, t2)
47+
}
48+
fn h<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
49+
(t1, t2)
50+
}
51+
}
52+
53+
#[rustc_macro_transparency = "transparent"]
54+
macro p($a:lifetime) {
55+
fn j<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
56+
(t1, t2)
57+
}
58+
fn k<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
59+
(t1, t2)
60+
}
61+
}
62+
63+
m!('a); //~ ERROR lifetime parameter `'a` only used once
64+
n!('a);
65+
p!('a);
66+
}
67+
68+
mod const_params {
69+
macro m($C:ident) {
70+
fn f<const $C: usize, const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); $C], [(); C]) {
71+
(t1, t2)
72+
}
73+
}
74+
75+
#[rustc_macro_transparency = "semitransparent"]
76+
macro n($C:ident) {
77+
fn g<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
78+
(t1, t2)
79+
}
80+
fn h<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
81+
(t1, t2)
82+
}
83+
}
84+
85+
#[rustc_macro_transparency = "transparent"]
86+
macro p($C:ident) {
87+
fn j<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
88+
(t1, t2)
89+
}
90+
fn k<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
91+
(t1, t2)
92+
}
93+
}
94+
95+
m!(C);
96+
n!(C);
97+
p!(C);
98+
}
99+
100+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error: lifetime parameter `'a` only used once
2+
--> $DIR/issue-104440.rs:63:8
3+
|
4+
LL | m!('a);
5+
| ^^
6+
| |
7+
| this lifetime...
8+
| ...is used only here
9+
|
10+
note: the lint level is defined here
11+
--> $DIR/issue-104440.rs:2:9
12+
|
13+
LL | #![deny(single_use_lifetimes)]
14+
| ^^^^^^^^^^^^^^^^^^^^
15+
16+
error: lifetime parameter `'a` only used once
17+
--> $DIR/issue-104440.rs:38:30
18+
|
19+
LL | fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) {
20+
| ^^ this lifetime... -- ...is used only here
21+
...
22+
LL | m!('a);
23+
| ------ in this macro invocation
24+
|
25+
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
26+
27+
error: aborting due to 2 previous errors
28+

0 commit comments

Comments
 (0)