Skip to content

structured suggestions for unused-lifetimes lint #54686

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 42 additions & 4 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ use hir::def::Def;
use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use hir::map::Map;
use hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, ParamName, Node};
use ty::{self, TyCtxt, GenericParamDefKind};
use ty::{self, TyCtxt, DefIdTree, GenericParamDefKind};

use errors::DiagnosticBuilder;
use errors::{Applicability, DiagnosticBuilder};
use rustc::lint;
use rustc_data_structures::sync::Lrc;
use session::Session;
Expand Down Expand Up @@ -1398,6 +1398,30 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults;
}

/// helper method to determine the span to remove when suggesting the
/// deletion of a lifetime
fn lifetime_deletion_span(&self, name: ast::Ident, generics: &hir::Generics) -> Option<Span> {
if generics.params.len() == 1 {
// if sole lifetime, remove the `<>` brackets
Some(generics.span)
} else {
generics.params.iter().enumerate()
.find_map(|(i, param)| {
if param.name.ident() == name {
// We also want to delete a leading or trailing comma
// as appropriate
if i >= generics.params.len() - 1 {
Some(generics.params[i-1].span.shrink_to_hi().to(param.span))
} else {
Some(param.span.to(generics.params[i+1].span.shrink_to_lo()))
}
} else {
None
}
})
}
}

fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
let defined_by = match self.scope {
Scope::Binder { lifetimes, .. } => lifetimes,
Expand Down Expand Up @@ -1468,12 +1492,26 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
_ => None,
} {
debug!("id ={:?} span = {:?} name = {:?}", node_id, span, name);
self.tcx.struct_span_lint_node(
let mut err = self.tcx.struct_span_lint_node(
lint::builtin::UNUSED_LIFETIMES,
id,
span,
&format!("lifetime parameter `{}` never used", name)
).emit();
);
if let Some(parent_def_id) = self.tcx.parent(def_id) {
if let Some(generics) = self.tcx.hir.get_generics(parent_def_id) {
let unused_lt_span = self.lifetime_deletion_span(name, generics);
if let Some(span) = unused_lt_span {
err.span_suggestion_with_applicability(
span,
"remove it",
String::new(),
Applicability::MachineApplicable
);
}
}
}
err.emit();
}
}
}
Expand Down
24 changes: 24 additions & 0 deletions src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// run-rustfix

// Test that we DO warn when lifetime name is not used at all.

#![deny(unused_lifetimes)]
#![allow(dead_code, unused_variables)]

fn september() {}
//~^ ERROR lifetime parameter `'a` never used
//~| HELP remove it

fn october<'b, T>(s: &'b T) -> &'b T {
//~^ ERROR lifetime parameter `'a` never used
//~| HELP remove it
s
}

fn november<'a>(s: &'a str) -> (&'a str) {
//~^ ERROR lifetime parameter `'b` never used
//~| HELP remove it
s
}

fn main() {}
31 changes: 18 additions & 13 deletions src/test/ui/single-use-lifetime/zero-uses-in-fn.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// run-rustfix

// Test that we DO warn when lifetime name is not used at all.

#![deny(unused_lifetimes)]
#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(dead_code, unused_variables)]

fn d<'a>() { } //~ ERROR `'a` never used
fn september<'a>() {}
//~^ ERROR lifetime parameter `'a` never used
//~| HELP remove it

fn main() { }
fn october<'a, 'b, T>(s: &'b T) -> &'b T {
//~^ ERROR lifetime parameter `'a` never used
//~| HELP remove it
s
}

fn november<'a, 'b>(s: &'a str) -> (&'a str) {
//~^ ERROR lifetime parameter `'b` never used
//~| HELP remove it
s
}

fn main() {}
26 changes: 21 additions & 5 deletions src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
error: lifetime parameter `'a` never used
--> $DIR/zero-uses-in-fn.rs:17:6
--> $DIR/zero-uses-in-fn.rs:8:14
|
LL | fn d<'a>() { } //~ ERROR `'a` never used
| ^^
LL | fn september<'a>() {}
| -^^- help: remove it
|
note: lint level defined here
--> $DIR/zero-uses-in-fn.rs:13:9
--> $DIR/zero-uses-in-fn.rs:5:9
|
LL | #![deny(unused_lifetimes)]
| ^^^^^^^^^^^^^^^^

error: aborting due to previous error
error: lifetime parameter `'a` never used
--> $DIR/zero-uses-in-fn.rs:12:12
|
LL | fn october<'a, 'b, T>(s: &'b T) -> &'b T {
| ^^--
| |
| help: remove it

error: lifetime parameter `'b` never used
--> $DIR/zero-uses-in-fn.rs:18:17
|
LL | fn november<'a, 'b>(s: &'a str) -> (&'a str) {
| --^^
| |
| help: remove it

error: aborting due to 3 previous errors

19 changes: 4 additions & 15 deletions src/test/ui/single-use-lifetime/zero-uses-in-impl.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test that we DO warn when lifetime name is not used at all.

#![deny(unused_lifetimes)]
#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(dead_code, unused_variables)]

struct Foo { }
struct Foo {}

impl<'a> Foo { } //~ ERROR `'a` never used
impl<'a> Foo {} //~ ERROR `'a` never used

fn main() { }
fn main() {}
8 changes: 4 additions & 4 deletions src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: lifetime parameter `'a` never used
--> $DIR/zero-uses-in-impl.rs:19:6
--> $DIR/zero-uses-in-impl.rs:8:6
|
LL | impl<'a> Foo { } //~ ERROR `'a` never used
| ^^
LL | impl<'a> Foo {} //~ ERROR `'a` never used
| -^^- help: remove it
|
note: lint level defined here
--> $DIR/zero-uses-in-impl.rs:13:9
--> $DIR/zero-uses-in-impl.rs:3:9
|
LL | #![deny(unused_lifetimes)]
| ^^^^^^^^^^^^^^^^
Expand Down