Skip to content

Commit

Permalink
fix #104440
Browse files Browse the repository at this point in the history
  • Loading branch information
TaKO8Ki committed Jan 16, 2023
1 parent d12412c commit fe96c11
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 25 deletions.
47 changes: 26 additions & 21 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,34 +825,39 @@ pub trait LintContext: Sized {
debug!(?param_span, ?use_span, ?deletion_span);
db.span_label(param_span, "this lifetime...");
db.span_label(use_span, "...is used only here");
let msg = "elide the single-use lifetime";
let (use_span, replace_lt) = if elide {
let use_span = sess.source_map().span_extend_while(
use_span,
char::is_whitespace,
).unwrap_or(use_span);
(use_span, String::new())
} else {
(use_span, "'_".to_owned())
};
db.multipart_suggestion(
msg,
vec![(deletion_span, String::new()), (use_span, replace_lt)],
Applicability::MachineApplicable,
);
if let Some(deletion_span) = deletion_span {
let msg = "elide the single-use lifetime";
let (use_span, replace_lt) = if elide {
let use_span = sess.source_map().span_extend_while(
use_span,
char::is_whitespace,
).unwrap_or(use_span);
(use_span, String::new())
} else {
(use_span, "'_".to_owned())
};
debug!(?deletion_span, ?use_span);
db.multipart_suggestion(
msg,
vec![(deletion_span, String::new()), (use_span, replace_lt)],
Applicability::MachineApplicable,
);
}
},
BuiltinLintDiagnostics::SingleUseLifetime {
param_span: _,
use_span: None,
deletion_span,
} => {
debug!(?deletion_span);
db.span_suggestion(
deletion_span,
"elide the unused lifetime",
"",
Applicability::MachineApplicable,
);
if let Some(deletion_span) = deletion_span {
db.span_suggestion(
deletion_span,
"elide the unused lifetime",
"",
Applicability::MachineApplicable,
);
}
},
BuiltinLintDiagnostics::NamedArgumentUsedPositionally{ position_sp_to_replace, position_sp_for_msg, named_arg_sp, named_arg_name, is_formatting_arg} => {
db.span_label(named_arg_sp, "this named argument is referred to by position in formatting string");
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ pub enum BuiltinLintDiagnostics {
param_span: Span,
/// Span of the code that should be removed when eliding this lifetime.
/// This span should include leading or trailing comma.
deletion_span: Span,
deletion_span: Option<Span>,
/// Span of the single use, or None if the lifetime is never used.
/// If true, the lifetime will be fully elided.
use_span: Option<(Span, bool)>,
Expand Down
22 changes: 19 additions & 3 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2188,15 +2188,31 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let deletion_span = || {
if params.len() == 1 {
// if sole lifetime, remove the entire `<>` brackets
generics_span
Some(generics_span)
} else if param_index == 0 {
// if removing within `<>` brackets, we also want to
// delete a leading or trailing comma as appropriate
param.span().to(params[param_index + 1].span().shrink_to_lo())
match (
param.span().find_ancestor_inside(generics_span),
params[param_index + 1].span().find_ancestor_inside(generics_span),
) {
(Some(param_span), Some(next_param_span)) => {
Some(param_span.to(next_param_span.shrink_to_lo()))
}
_ => None,
}
} else {
// if removing within `<>` brackets, we also want to
// delete a leading or trailing comma as appropriate
params[param_index - 1].span().shrink_to_hi().to(param.span())
match (
param.span().find_ancestor_inside(generics_span),
params[param_index - 1].span().find_ancestor_inside(generics_span),
) {
(Some(param_span), Some(prev_param_span)) => {
Some(prev_param_span.shrink_to_hi().to(param_span))
}
_ => None,
}
}
};
match use_set {
Expand Down
100 changes: 100 additions & 0 deletions tests/ui/single-use-lifetime/issue-104440.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#![feature(decl_macro, rustc_attrs)]
#![deny(single_use_lifetimes)]

mod type_params {
macro m($T:ident) {
fn f<$T: Clone, T: PartialEq>(t1: $T, t2: T) -> ($T, bool) {
(t1.clone(), t2 == t2)
}
}

#[rustc_macro_transparency = "semitransparent"]
macro n($T:ident) {
fn g<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
(t1.clone(), t2.clone())
}
fn h<T: Clone>(t1: $T, t2: T) -> (T, $T) {
(t1.clone(), t2.clone())
}
}

#[rustc_macro_transparency = "transparent"]
macro p($T:ident) {
fn j<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
(t1.clone(), t2.clone())
}
fn k<T: Clone>(t1: $T, t2: T) -> (T, $T) {
(t1.clone(), t2.clone())
}
}

m!(T);
n!(T);
p!(T);
}

mod lifetime_params {
macro m($a:lifetime) {
fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) { //~ ERROR lifetime parameter `'a` only used once
(t1, t2)
}
}

#[rustc_macro_transparency = "semitransparent"]
macro n($a:lifetime) {
fn g<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
(t1, t2)
}
fn h<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
(t1, t2)
}
}

#[rustc_macro_transparency = "transparent"]
macro p($a:lifetime) {
fn j<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
(t1, t2)
}
fn k<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
(t1, t2)
}
}

m!('a); //~ ERROR lifetime parameter `'a` only used once
n!('a);
p!('a);
}

mod const_params {
macro m($C:ident) {
fn f<const $C: usize, const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); $C], [(); C]) {
(t1, t2)
}
}

#[rustc_macro_transparency = "semitransparent"]
macro n($C:ident) {
fn g<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
(t1, t2)
}
fn h<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
(t1, t2)
}
}

#[rustc_macro_transparency = "transparent"]
macro p($C:ident) {
fn j<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
(t1, t2)
}
fn k<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
(t1, t2)
}
}

m!(C);
n!(C);
p!(C);
}

fn main() {}
28 changes: 28 additions & 0 deletions tests/ui/single-use-lifetime/issue-104440.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
error: lifetime parameter `'a` only used once
--> $DIR/issue-104440.rs:63:8
|
LL | m!('a);
| ^^
| |
| this lifetime...
| ...is used only here
|
note: the lint level is defined here
--> $DIR/issue-104440.rs:2:9
|
LL | #![deny(single_use_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^

error: lifetime parameter `'a` only used once
--> $DIR/issue-104440.rs:38:30
|
LL | fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) {
| ^^ this lifetime... -- ...is used only here
...
LL | m!('a);
| ------ in this macro invocation
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 2 previous errors

0 comments on commit fe96c11

Please sign in to comment.