mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 01:34:21 +00:00
Add machine applicable suggestion for needless_lifetimes
Also adds a test for #5787
This commit is contained in:
parent
607e3e893e
commit
6a8b20230b
@ -1,22 +1,21 @@
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::trait_ref_of_method;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
|
||||
use rustc_hir::intravisit::{
|
||||
walk_fn_decl, walk_generic_arg, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
|
||||
walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
|
||||
walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor,
|
||||
};
|
||||
use rustc_hir::lang_items;
|
||||
use rustc_hir::FnRetTy::Return;
|
||||
use rustc_hir::{
|
||||
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
|
||||
ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, PolyTraitRef, PredicateOrigin, TraitFn,
|
||||
TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
|
||||
lang_items, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics,
|
||||
Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
|
||||
PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::hir::nested_filter as middle_nested_filter;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::source_map::Span;
|
||||
@ -35,8 +34,6 @@ declare_clippy_lint! {
|
||||
/// ### Known problems
|
||||
/// - We bail out if the function has a `where` clause where lifetimes
|
||||
/// are mentioned due to potential false positives.
|
||||
/// - Lifetime bounds such as `impl Foo + 'a` and `T: 'a` must be elided with the
|
||||
/// placeholder notation `'_` because the fully elided notation leaves the type bound to `'static`.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
@ -94,7 +91,7 @@ declare_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]);
|
||||
impl<'tcx> LateLintPass<'tcx> for Lifetimes {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Fn(ref sig, generics, id) = item.kind {
|
||||
check_fn_inner(cx, sig.decl, Some(id), None, generics, item.span, true);
|
||||
check_fn_inner(cx, sig, Some(id), None, generics, item.span, true);
|
||||
} else if let ItemKind::Impl(impl_) = item.kind {
|
||||
if !item.span.from_expansion() {
|
||||
report_extra_impl_lifetimes(cx, impl_);
|
||||
@ -107,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
|
||||
let report_extra_lifetimes = trait_ref_of_method(cx, item.owner_id.def_id).is_none();
|
||||
check_fn_inner(
|
||||
cx,
|
||||
sig.decl,
|
||||
sig,
|
||||
Some(id),
|
||||
None,
|
||||
item.generics,
|
||||
@ -123,22 +120,14 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
|
||||
TraitFn::Required(sig) => (None, Some(sig)),
|
||||
TraitFn::Provided(id) => (Some(id), None),
|
||||
};
|
||||
check_fn_inner(cx, sig.decl, body, trait_sig, item.generics, item.span, true);
|
||||
check_fn_inner(cx, sig, body, trait_sig, item.generics, item.span, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The lifetime of a &-reference.
|
||||
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
|
||||
enum RefLt {
|
||||
Unnamed,
|
||||
Static,
|
||||
Named(LocalDefId),
|
||||
}
|
||||
|
||||
fn check_fn_inner<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
decl: &'tcx FnDecl<'_>,
|
||||
sig: &'tcx FnSig<'_>,
|
||||
body: Option<BodyId>,
|
||||
trait_sig: Option<&[Ident]>,
|
||||
generics: &'tcx Generics<'_>,
|
||||
@ -164,7 +153,7 @@ fn check_fn_inner<'tcx>(
|
||||
for bound in pred.bounds {
|
||||
let mut visitor = RefVisitor::new(cx);
|
||||
walk_param_bound(&mut visitor, bound);
|
||||
if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) {
|
||||
if visitor.lts.iter().any(|lt| matches!(lt.res, LifetimeName::Param(_))) {
|
||||
return;
|
||||
}
|
||||
if let GenericBound::Trait(ref trait_ref, _) = *bound {
|
||||
@ -191,12 +180,12 @@ fn check_fn_inner<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(elidable_lts) = could_use_elision(cx, decl, body, trait_sig, generics.params) {
|
||||
if let Some((elidable_lts, usages)) = could_use_elision(cx, sig.decl, body, trait_sig, generics.params) {
|
||||
let lts = elidable_lts
|
||||
.iter()
|
||||
// In principle, the result of the call to `Node::ident` could be `unwrap`ped, as `DefId` should refer to a
|
||||
// `Node::GenericParam`.
|
||||
.filter_map(|&(def_id, _)| cx.tcx.hir().get_by_def_id(def_id).ident())
|
||||
.filter_map(|&def_id| cx.tcx.hir().get_by_def_id(def_id).ident())
|
||||
.map(|ident| ident.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
@ -204,21 +193,99 @@ fn check_fn_inner<'tcx>(
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
NEEDLESS_LIFETIMES,
|
||||
span.with_hi(decl.output.span().hi()),
|
||||
span.with_hi(sig.decl.output.span().hi()),
|
||||
&format!("the following explicit lifetimes could be elided: {lts}"),
|
||||
|diag| {
|
||||
if let Some(span) = elidable_lts.iter().find_map(|&(_, span)| span) {
|
||||
diag.span_help(span, "replace with `'_` in generic arguments such as here");
|
||||
if sig.header.is_async() {
|
||||
// async functions have usages whose spans point at the lifetime declaration which messes up
|
||||
// suggestions
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(suggestions) = elision_suggestions(cx, generics, &elidable_lts, &usages) {
|
||||
diag.multipart_suggestion("elide the lifetimes", suggestions, Applicability::MachineApplicable);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if report_extra_lifetimes {
|
||||
self::report_extra_lifetimes(cx, decl, generics);
|
||||
self::report_extra_lifetimes(cx, sig.decl, generics);
|
||||
}
|
||||
}
|
||||
|
||||
fn elision_suggestions(
|
||||
cx: &LateContext<'_>,
|
||||
generics: &Generics<'_>,
|
||||
elidable_lts: &[LocalDefId],
|
||||
usages: &[Lifetime],
|
||||
) -> Option<Vec<(Span, String)>> {
|
||||
let explicit_params = generics
|
||||
.params
|
||||
.iter()
|
||||
.filter(|param| !param.is_elided_lifetime() && !param.is_impl_trait())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut suggestions = if elidable_lts.len() == explicit_params.len() {
|
||||
// if all the params are elided remove the whole generic block
|
||||
//
|
||||
// fn x<'a>() {}
|
||||
// ^^^^
|
||||
vec![(generics.span, String::new())]
|
||||
} else {
|
||||
elidable_lts
|
||||
.iter()
|
||||
.map(|&id| {
|
||||
let pos = explicit_params.iter().position(|param| param.def_id == id)?;
|
||||
let param = explicit_params.get(pos)?;
|
||||
|
||||
let span = if let Some(next) = explicit_params.get(pos + 1) {
|
||||
// fn x<'prev, 'a, 'next>() {}
|
||||
// ^^^^
|
||||
param.span.until(next.span)
|
||||
} else {
|
||||
// `pos` should be at least 1 here, because the param in position 0 would either have a `next`
|
||||
// param or would have taken the `elidable_lts.len() == explicit_params.len()` branch.
|
||||
let prev = explicit_params.get(pos - 1)?;
|
||||
|
||||
// fn x<'prev, 'a>() {}
|
||||
// ^^^^
|
||||
param.span.with_lo(prev.span.hi())
|
||||
};
|
||||
|
||||
Some((span, String::new()))
|
||||
})
|
||||
.collect::<Option<Vec<_>>>()?
|
||||
};
|
||||
|
||||
suggestions.extend(
|
||||
usages
|
||||
.iter()
|
||||
.filter(|usage| named_lifetime(usage).map_or(false, |id| elidable_lts.contains(&id)))
|
||||
.map(|usage| {
|
||||
match cx.tcx.hir().get_parent(usage.hir_id) {
|
||||
Node::Ty(Ty {
|
||||
kind: TyKind::Ref(..), ..
|
||||
}) => {
|
||||
// expand `&'a T` to `&'a T`
|
||||
// ^^ ^^^
|
||||
let span = cx
|
||||
.sess()
|
||||
.source_map()
|
||||
.span_extend_while(usage.ident.span, |ch| ch.is_ascii_whitespace())
|
||||
.unwrap_or(usage.ident.span);
|
||||
|
||||
(span, String::new())
|
||||
},
|
||||
// `T<'a>` and `impl Foo + 'a` should be replaced by `'_`
|
||||
_ => (usage.ident.span, String::from("'_")),
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
Some(suggestions)
|
||||
}
|
||||
|
||||
// elision doesn't work for explicit self types, see rust-lang/rust#69064
|
||||
fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>) -> bool {
|
||||
if_chain! {
|
||||
@ -238,13 +305,20 @@ fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident:
|
||||
}
|
||||
}
|
||||
|
||||
fn named_lifetime(lt: &Lifetime) -> Option<LocalDefId> {
|
||||
match lt.res {
|
||||
LifetimeName::Param(id) if !lt.is_anonymous() => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn could_use_elision<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
func: &'tcx FnDecl<'_>,
|
||||
body: Option<BodyId>,
|
||||
trait_sig: Option<&[Ident]>,
|
||||
named_generics: &'tcx [GenericParam<'_>],
|
||||
) -> Option<Vec<(LocalDefId, Option<Span>)>> {
|
||||
) -> Option<(Vec<LocalDefId>, Vec<Lifetime>)> {
|
||||
// There are two scenarios where elision works:
|
||||
// * no output references, all input references have different LT
|
||||
// * output references, exactly one input reference with same LT
|
||||
@ -252,7 +326,7 @@ fn could_use_elision<'tcx>(
|
||||
// level of the current item.
|
||||
|
||||
// check named LTs
|
||||
let allowed_lts = allowed_lts_from(cx.tcx, named_generics);
|
||||
let allowed_lts = allowed_lts_from(named_generics);
|
||||
|
||||
// these will collect all the lifetimes for references in arg/return types
|
||||
let mut input_visitor = RefVisitor::new(cx);
|
||||
@ -302,32 +376,24 @@ fn could_use_elision<'tcx>(
|
||||
|
||||
// check for lifetimes from higher scopes
|
||||
for lt in input_lts.iter().chain(output_lts.iter()) {
|
||||
if !allowed_lts.contains(lt) {
|
||||
if let Some(id) = named_lifetime(lt)
|
||||
&& !allowed_lts.contains(&id)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
// check for higher-ranked trait bounds
|
||||
if !input_visitor.nested_elision_site_lts.is_empty() || !output_visitor.nested_elision_site_lts.is_empty() {
|
||||
let allowed_lts: FxHashSet<_> = allowed_lts
|
||||
.iter()
|
||||
.filter_map(|lt| match lt {
|
||||
RefLt::Named(def_id) => Some(cx.tcx.item_name(def_id.to_def_id())),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
let allowed_lts: FxHashSet<_> = allowed_lts.iter().map(|id| cx.tcx.item_name(id.to_def_id())).collect();
|
||||
for lt in input_visitor.nested_elision_site_lts {
|
||||
if let RefLt::Named(def_id) = lt {
|
||||
if allowed_lts.contains(&cx.tcx.item_name(def_id.to_def_id())) {
|
||||
return None;
|
||||
}
|
||||
if allowed_lts.contains(<.ident.name) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
for lt in output_visitor.nested_elision_site_lts {
|
||||
if let RefLt::Named(def_id) = lt {
|
||||
if allowed_lts.contains(&cx.tcx.item_name(def_id.to_def_id())) {
|
||||
return None;
|
||||
}
|
||||
if allowed_lts.contains(<.ident.name) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -339,15 +405,10 @@ fn could_use_elision<'tcx>(
|
||||
let elidable_lts = named_lifetime_occurrences(&input_lts)
|
||||
.into_iter()
|
||||
.filter_map(|(def_id, occurrences)| {
|
||||
if occurrences == 1 && (input_lts.len() == 1 || !output_lts.contains(&RefLt::Named(def_id))) {
|
||||
Some((
|
||||
def_id,
|
||||
input_visitor
|
||||
.lifetime_generic_arg_spans
|
||||
.get(&def_id)
|
||||
.or_else(|| output_visitor.lifetime_generic_arg_spans.get(&def_id))
|
||||
.copied(),
|
||||
))
|
||||
if occurrences == 1
|
||||
&& (input_lts.len() == 1 || !output_lts.iter().any(|lt| named_lifetime(lt) == Some(def_id)))
|
||||
{
|
||||
Some(def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -355,31 +416,34 @@ fn could_use_elision<'tcx>(
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if elidable_lts.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(elidable_lts)
|
||||
return None;
|
||||
}
|
||||
|
||||
let usages = itertools::chain(input_lts, output_lts).collect();
|
||||
|
||||
Some((elidable_lts, usages))
|
||||
}
|
||||
|
||||
fn allowed_lts_from(tcx: TyCtxt<'_>, named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
|
||||
let mut allowed_lts = FxHashSet::default();
|
||||
for par in named_generics.iter() {
|
||||
if let GenericParamKind::Lifetime { .. } = par.kind {
|
||||
allowed_lts.insert(RefLt::Named(tcx.hir().local_def_id(par.hir_id)));
|
||||
}
|
||||
}
|
||||
allowed_lts.insert(RefLt::Unnamed);
|
||||
allowed_lts.insert(RefLt::Static);
|
||||
allowed_lts
|
||||
fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<LocalDefId> {
|
||||
named_generics
|
||||
.iter()
|
||||
.filter_map(|par| {
|
||||
if let GenericParamKind::Lifetime { .. } = par.kind {
|
||||
Some(par.def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Number of times each named lifetime occurs in the given slice. Returns a vector to preserve
|
||||
/// relative order.
|
||||
#[must_use]
|
||||
fn named_lifetime_occurrences(lts: &[RefLt]) -> Vec<(LocalDefId, usize)> {
|
||||
fn named_lifetime_occurrences(lts: &[Lifetime]) -> Vec<(LocalDefId, usize)> {
|
||||
let mut occurrences = Vec::new();
|
||||
for lt in lts {
|
||||
if let &RefLt::Named(curr_def_id) = lt {
|
||||
if let Some(curr_def_id) = named_lifetime(lt) {
|
||||
if let Some(pair) = occurrences
|
||||
.iter_mut()
|
||||
.find(|(prev_def_id, _)| *prev_def_id == curr_def_id)
|
||||
@ -393,12 +457,10 @@ fn named_lifetime_occurrences(lts: &[RefLt]) -> Vec<(LocalDefId, usize)> {
|
||||
occurrences
|
||||
}
|
||||
|
||||
/// A visitor usable for `rustc_front::visit::walk_ty()`.
|
||||
struct RefVisitor<'a, 'tcx> {
|
||||
cx: &'a LateContext<'tcx>,
|
||||
lts: Vec<RefLt>,
|
||||
lifetime_generic_arg_spans: FxHashMap<LocalDefId, Span>,
|
||||
nested_elision_site_lts: Vec<RefLt>,
|
||||
lts: Vec<Lifetime>,
|
||||
nested_elision_site_lts: Vec<Lifetime>,
|
||||
unelided_trait_object_lifetime: bool,
|
||||
}
|
||||
|
||||
@ -407,32 +469,16 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
|
||||
Self {
|
||||
cx,
|
||||
lts: Vec::new(),
|
||||
lifetime_generic_arg_spans: FxHashMap::default(),
|
||||
nested_elision_site_lts: Vec::new(),
|
||||
unelided_trait_object_lifetime: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn record(&mut self, lifetime: &Option<Lifetime>) {
|
||||
if let Some(ref lt) = *lifetime {
|
||||
if lt.is_static() {
|
||||
self.lts.push(RefLt::Static);
|
||||
} else if lt.is_anonymous() {
|
||||
// Fresh lifetimes generated should be ignored.
|
||||
self.lts.push(RefLt::Unnamed);
|
||||
} else if let LifetimeName::Param(def_id) = lt.res {
|
||||
self.lts.push(RefLt::Named(def_id));
|
||||
}
|
||||
} else {
|
||||
self.lts.push(RefLt::Unnamed);
|
||||
}
|
||||
}
|
||||
|
||||
fn all_lts(&self) -> Vec<RefLt> {
|
||||
fn all_lts(&self) -> Vec<Lifetime> {
|
||||
self.lts
|
||||
.iter()
|
||||
.chain(self.nested_elision_site_lts.iter())
|
||||
.cloned()
|
||||
.copied()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
@ -444,7 +490,7 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
|
||||
impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
||||
// for lifetimes as parameters of generics
|
||||
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
|
||||
self.record(&Some(*lifetime));
|
||||
self.lts.push(*lifetime);
|
||||
}
|
||||
|
||||
fn visit_poly_trait_ref(&mut self, poly_tref: &'tcx PolyTraitRef<'tcx>) {
|
||||
@ -469,11 +515,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
||||
walk_item(self, item);
|
||||
self.lts.truncate(len);
|
||||
self.lts.extend(bounds.iter().filter_map(|bound| match bound {
|
||||
GenericArg::Lifetime(l) => Some(if let LifetimeName::Param(def_id) = l.res {
|
||||
RefLt::Named(def_id)
|
||||
} else {
|
||||
RefLt::Unnamed
|
||||
}),
|
||||
GenericArg::Lifetime(&l) => Some(l),
|
||||
_ => None,
|
||||
}));
|
||||
},
|
||||
@ -493,13 +535,6 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
||||
_ => walk_ty(self, ty),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_generic_arg(&mut self, generic_arg: &'tcx GenericArg<'tcx>) {
|
||||
if let GenericArg::Lifetime(l) = generic_arg && let LifetimeName::Param(def_id) = l.res {
|
||||
self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.ident.span);
|
||||
}
|
||||
walk_generic_arg(self, generic_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/// Are any lifetimes mentioned in the `where` clause? If so, we don't try to
|
||||
@ -517,14 +552,18 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
|
||||
return true;
|
||||
}
|
||||
// if the bounds define new lifetimes, they are fine to occur
|
||||
let allowed_lts = allowed_lts_from(cx.tcx, pred.bound_generic_params);
|
||||
let allowed_lts = allowed_lts_from(pred.bound_generic_params);
|
||||
// now walk the bounds
|
||||
for bound in pred.bounds.iter() {
|
||||
walk_param_bound(&mut visitor, bound);
|
||||
}
|
||||
// and check that all lifetimes are allowed
|
||||
if visitor.all_lts().iter().any(|it| !allowed_lts.contains(it)) {
|
||||
return true;
|
||||
for lt in visitor.all_lts() {
|
||||
if let Some(id) = named_lifetime(<)
|
||||
&& !allowed_lts.contains(&id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
WherePredicate::EqPredicate(ref pred) => {
|
||||
|
@ -5,6 +5,11 @@ LL | pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::needless-lifetimes` implied by `-D warnings`
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
|
||||
LL + pub fn add_barfoos_to_foos(bars: &HashSet<&Bar>) {
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -9,6 +9,11 @@ note: the lint level is defined here
|
||||
|
|
||||
LL | #![deny(clippy::needless_lifetimes)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn baz<'a>(&'a self) -> impl Foo + 'a {
|
||||
LL + fn baz(&self) -> impl Foo + '_ {
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
537
tests/ui/needless_lifetimes.fixed
Normal file
537
tests/ui/needless_lifetimes.fixed
Normal file
@ -0,0 +1,537 @@
|
||||
// run-rustfix
|
||||
// aux-build:macro_rules.rs
|
||||
|
||||
#![warn(clippy::needless_lifetimes)]
|
||||
#![allow(
|
||||
unused,
|
||||
clippy::boxed_local,
|
||||
clippy::needless_pass_by_value,
|
||||
clippy::unnecessary_wraps,
|
||||
dyn_drop,
|
||||
clippy::get_first
|
||||
)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate macro_rules;
|
||||
|
||||
fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
|
||||
|
||||
fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {}
|
||||
|
||||
// No error; same lifetime on two params.
|
||||
fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {}
|
||||
|
||||
// No error; static involved.
|
||||
fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {}
|
||||
|
||||
fn mut_and_static_input(_x: &mut u8, _y: &'static str) {}
|
||||
|
||||
fn in_and_out(x: &u8, _y: u8) -> &u8 {
|
||||
x
|
||||
}
|
||||
|
||||
// No error; multiple input refs.
|
||||
fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 {
|
||||
x
|
||||
}
|
||||
|
||||
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||
// fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8
|
||||
// ^^^
|
||||
fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 {
|
||||
x
|
||||
}
|
||||
|
||||
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||
// fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8
|
||||
// ^^^
|
||||
fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 {
|
||||
y
|
||||
}
|
||||
|
||||
// No error; multiple input refs
|
||||
async fn func<'a>(args: &[&'a str]) -> Option<&'a str> {
|
||||
args.get(0).cloned()
|
||||
}
|
||||
|
||||
// No error; static involved.
|
||||
fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
|
||||
x
|
||||
}
|
||||
|
||||
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||
// fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()>
|
||||
// ^^^
|
||||
fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> {
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||
// fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()>
|
||||
// ^^^
|
||||
fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> {
|
||||
Ok(y)
|
||||
}
|
||||
|
||||
// No error; two input refs.
|
||||
fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 {
|
||||
x.unwrap()
|
||||
}
|
||||
|
||||
fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> {
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
// Where-clause, but without lifetimes.
|
||||
fn where_clause_without_lt<T>(x: &u8, _y: u8) -> Result<&u8, ()>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
type Ref<'r> = &'r u8;
|
||||
|
||||
// No error; same lifetime on two params.
|
||||
fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {}
|
||||
|
||||
fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {}
|
||||
|
||||
// No error; bounded lifetime.
|
||||
fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {}
|
||||
|
||||
// No error; bounded lifetime.
|
||||
fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8)
|
||||
where
|
||||
'b: 'a,
|
||||
{
|
||||
}
|
||||
|
||||
struct Lt<'a, I: 'static> {
|
||||
x: &'a I,
|
||||
}
|
||||
|
||||
// No error; fn bound references `'a`.
|
||||
fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
|
||||
where
|
||||
F: Fn(Lt<'a, I>) -> Lt<'a, I>,
|
||||
{
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn fn_bound_2<F, I>(_m: Lt<'_, I>, _f: F) -> Lt<'_, I>
|
||||
where
|
||||
for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>,
|
||||
{
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// No error; see below.
|
||||
fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) {
|
||||
f(x);
|
||||
}
|
||||
|
||||
fn fn_bound_3_cannot_elide() {
|
||||
let x = 42;
|
||||
let p = &x;
|
||||
let mut q = &x;
|
||||
// This will fail if we elide lifetimes of `fn_bound_3`.
|
||||
fn_bound_3(p, |y| q = y);
|
||||
}
|
||||
|
||||
// No error; multiple input refs.
|
||||
fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () {
|
||||
if cond { x } else { f() }
|
||||
}
|
||||
|
||||
struct X {
|
||||
x: u8,
|
||||
}
|
||||
|
||||
impl X {
|
||||
fn self_and_out(&self) -> &u8 {
|
||||
&self.x
|
||||
}
|
||||
|
||||
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||
// fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8
|
||||
// ^^^
|
||||
fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
|
||||
&self.x
|
||||
}
|
||||
|
||||
// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
|
||||
// fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8
|
||||
// ^^^^^
|
||||
fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
|
||||
x
|
||||
}
|
||||
|
||||
fn distinct_self_and_in(&self, _x: &u8) {}
|
||||
|
||||
// No error; same lifetimes on two params.
|
||||
fn self_and_same_in<'s>(&'s self, _x: &'s u8) {}
|
||||
}
|
||||
|
||||
struct Foo<'a>(&'a u8);
|
||||
|
||||
impl<'a> Foo<'a> {
|
||||
// No error; lifetime `'a` not defined in method.
|
||||
fn self_shared_lifetime(&self, _: &'a u8) {}
|
||||
// No error; bounds exist.
|
||||
fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {}
|
||||
}
|
||||
|
||||
fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn struct_with_lt(_foo: Foo<'_>) -> &str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// No warning; two input lifetimes (named on the reference, anonymous on `Foo`).
|
||||
fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// No warning; two input lifetimes (anonymous on the reference, named on `Foo`).
|
||||
fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
|
||||
// valid:
|
||||
// fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str
|
||||
// ^^
|
||||
fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
|
||||
// valid:
|
||||
// fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str
|
||||
// ^^^^
|
||||
fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
trait WithLifetime<'a> {}
|
||||
|
||||
type WithLifetimeAlias<'a> = dyn WithLifetime<'a>;
|
||||
|
||||
// Should not warn because it won't build without the lifetime.
|
||||
fn trait_obj_elided<'a>(_arg: &'a dyn WithLifetime) -> &'a str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// Should warn because there is no lifetime on `Drop`, so this would be
|
||||
// unambiguous if we elided the lifetime.
|
||||
fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
type FooAlias<'a> = Foo<'a>;
|
||||
|
||||
fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`).
|
||||
fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`).
|
||||
fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
|
||||
// valid:
|
||||
// fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str
|
||||
// ^^
|
||||
fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
|
||||
// valid:
|
||||
// fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str
|
||||
// ^^^^^^^^^
|
||||
fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn named_input_elided_output(_arg: &str) -> &str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn elided_input_named_output<'a>(_arg: &str) -> &'a str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// Don't warn on these; see issue #292.
|
||||
fn trait_bound_bug<'a, T: WithLifetime<'a>>() {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// See issue #740.
|
||||
struct Test {
|
||||
vec: Vec<usize>,
|
||||
}
|
||||
|
||||
impl Test {
|
||||
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = usize> + 'a> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
trait LintContext<'a> {}
|
||||
|
||||
fn f<'a, T: LintContext<'a>>(_: &T) {}
|
||||
|
||||
fn test<'a>(x: &'a [u8]) -> u8 {
|
||||
let y: &'a u8 = &x[5];
|
||||
*y
|
||||
}
|
||||
|
||||
// Issue #3284: give hint regarding lifetime in return type.
|
||||
struct Cow<'a> {
|
||||
x: &'a str,
|
||||
}
|
||||
fn out_return_type_lts(e: &str) -> Cow<'_> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// Make sure we still warn on implementations
|
||||
mod issue4291 {
|
||||
trait BadTrait {
|
||||
fn needless_lt(x: &u8) {}
|
||||
}
|
||||
|
||||
impl BadTrait for () {
|
||||
fn needless_lt(_x: &u8) {}
|
||||
}
|
||||
}
|
||||
|
||||
mod issue2944 {
|
||||
trait Foo {}
|
||||
struct Bar;
|
||||
struct Baz<'a> {
|
||||
bar: &'a Bar,
|
||||
}
|
||||
|
||||
impl<'a> Foo for Baz<'a> {}
|
||||
impl Bar {
|
||||
fn baz(&self) -> impl Foo + '_ {
|
||||
Baz { bar: self }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod nested_elision_sites {
|
||||
// issue #issue2944
|
||||
|
||||
// closure trait bounds subject to nested elision
|
||||
// don't lint because they refer to outer lifetimes
|
||||
fn trait_fn<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
|
||||
move || i
|
||||
}
|
||||
fn trait_fn_mut<'a>(i: &'a i32) -> impl FnMut() -> &'a i32 {
|
||||
move || i
|
||||
}
|
||||
fn trait_fn_once<'a>(i: &'a i32) -> impl FnOnce() -> &'a i32 {
|
||||
move || i
|
||||
}
|
||||
|
||||
// don't lint
|
||||
fn impl_trait_in_input_position<'a>(f: impl Fn() -> &'a i32) -> &'a i32 {
|
||||
f()
|
||||
}
|
||||
fn impl_trait_in_output_position<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
|
||||
move || i
|
||||
}
|
||||
// lint
|
||||
fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 {
|
||||
f(i)
|
||||
}
|
||||
fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&i32) -> &i32) -> &i32 {
|
||||
f(i)
|
||||
}
|
||||
|
||||
// don't lint
|
||||
fn generics_not_elidable<'a, T: Fn() -> &'a i32>(f: T) -> &'a i32 {
|
||||
f()
|
||||
}
|
||||
// lint
|
||||
fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
|
||||
f(i)
|
||||
}
|
||||
|
||||
// don't lint
|
||||
fn where_clause_not_elidable<'a, T>(f: T) -> &'a i32
|
||||
where
|
||||
T: Fn() -> &'a i32,
|
||||
{
|
||||
f()
|
||||
}
|
||||
// lint
|
||||
fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
|
||||
where
|
||||
T: Fn(&i32) -> &i32,
|
||||
{
|
||||
f(i)
|
||||
}
|
||||
|
||||
// don't lint
|
||||
fn pointer_fn_in_input_position<'a>(f: fn(&'a i32) -> &'a i32, i: &'a i32) -> &'a i32 {
|
||||
f(i)
|
||||
}
|
||||
fn pointer_fn_in_output_position<'a>(_: &'a i32) -> fn(&'a i32) -> &'a i32 {
|
||||
|i| i
|
||||
}
|
||||
// lint
|
||||
fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
|
||||
f(i)
|
||||
}
|
||||
|
||||
// don't lint
|
||||
fn nested_fn_pointer_1<'a>(_: &'a i32) -> fn(fn(&'a i32) -> &'a i32) -> i32 {
|
||||
|f| 42
|
||||
}
|
||||
fn nested_fn_pointer_2<'a>(_: &'a i32) -> impl Fn(fn(&'a i32)) {
|
||||
|f| ()
|
||||
}
|
||||
|
||||
// lint
|
||||
fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
|
||||
|f| 42
|
||||
}
|
||||
fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
|
||||
|f| ()
|
||||
}
|
||||
}
|
||||
|
||||
mod issue6159 {
|
||||
use std::ops::Deref;
|
||||
pub fn apply_deref<'a, T, F, R>(x: &'a T, f: F) -> R
|
||||
where
|
||||
T: Deref,
|
||||
F: FnOnce(&'a T::Target) -> R,
|
||||
{
|
||||
f(x.deref())
|
||||
}
|
||||
}
|
||||
|
||||
mod issue7296 {
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
fn implicit(&self) -> &() {
|
||||
&()
|
||||
}
|
||||
fn implicit_mut(&mut self) -> &() {
|
||||
&()
|
||||
}
|
||||
|
||||
fn explicit<'a>(self: &'a Arc<Self>) -> &'a () {
|
||||
&()
|
||||
}
|
||||
fn explicit_mut<'a>(self: &'a mut Rc<Self>) -> &'a () {
|
||||
&()
|
||||
}
|
||||
|
||||
fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
|
||||
&()
|
||||
}
|
||||
}
|
||||
|
||||
trait Bar {
|
||||
fn implicit(&self) -> &();
|
||||
fn implicit_provided(&self) -> &() {
|
||||
&()
|
||||
}
|
||||
|
||||
fn explicit<'a>(self: &'a Arc<Self>) -> &'a ();
|
||||
fn explicit_provided<'a>(self: &'a Arc<Self>) -> &'a () {
|
||||
&()
|
||||
}
|
||||
|
||||
fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
|
||||
fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
|
||||
&()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod pr_9743_false_negative_fix {
|
||||
#![allow(unused)]
|
||||
|
||||
fn foo(x: &u8, y: &'_ u8) {}
|
||||
|
||||
fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
|
||||
}
|
||||
|
||||
mod pr_9743_output_lifetime_checks {
|
||||
#![allow(unused)]
|
||||
|
||||
// lint: only one input
|
||||
fn one_input(x: &u8) -> &u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// lint: multiple inputs, output would not be elided
|
||||
fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) -> &'b u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
// don't lint: multiple inputs, output would be elided (which would create an ambiguity)
|
||||
fn multiple_inputs_output_would_be_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'a u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
mod in_macro {
|
||||
macro_rules! local_one_input_macro {
|
||||
() => {
|
||||
fn one_input(x: &u8) -> &u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// lint local macro expands to function with needless lifetimes
|
||||
local_one_input_macro!();
|
||||
|
||||
// no lint on external macro
|
||||
macro_rules::needless_lifetime!();
|
||||
}
|
||||
|
||||
mod issue5787 {
|
||||
use std::sync::MutexGuard;
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
// doesn't get linted without async
|
||||
pub async fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
|
||||
guard
|
||||
}
|
||||
}
|
||||
|
||||
async fn foo<'a>(_x: &i32, y: &'a str) -> &'a str {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,7 +1,9 @@
|
||||
// run-rustfix
|
||||
// aux-build:macro_rules.rs
|
||||
|
||||
#![warn(clippy::needless_lifetimes)]
|
||||
#![allow(
|
||||
dead_code,
|
||||
unused,
|
||||
clippy::boxed_local,
|
||||
clippy::needless_pass_by_value,
|
||||
clippy::unnecessary_wraps,
|
||||
@ -515,4 +517,21 @@ mod in_macro {
|
||||
macro_rules::needless_lifetime!();
|
||||
}
|
||||
|
||||
mod issue5787 {
|
||||
use std::sync::MutexGuard;
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
// doesn't get linted without async
|
||||
pub async fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
|
||||
guard
|
||||
}
|
||||
}
|
||||
|
||||
async fn foo<'a>(_x: &i32, y: &'a str) -> &'a str {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,319 +1,546 @@
|
||||
error: the following explicit lifetimes could be elided: 'a, 'b
|
||||
--> $DIR/needless_lifetimes.rs:15:1
|
||||
--> $DIR/needless_lifetimes.rs:17:1
|
||||
|
|
||||
LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::needless-lifetimes` implied by `-D warnings`
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
|
||||
LL + fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a, 'b
|
||||
--> $DIR/needless_lifetimes.rs:17:1
|
||||
--> $DIR/needless_lifetimes.rs:19:1
|
||||
|
|
||||
LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
|
||||
LL + fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {}
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:27:1
|
||||
--> $DIR/needless_lifetimes.rs:29:1
|
||||
|
|
||||
LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
|
||||
LL + fn in_and_out(x: &u8, _y: u8) -> &u8 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'b
|
||||
--> $DIR/needless_lifetimes.rs:39:1
|
||||
--> $DIR/needless_lifetimes.rs:41:1
|
||||
|
|
||||
LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
|
||||
LL + fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:46:1
|
||||
--> $DIR/needless_lifetimes.rs:48:1
|
||||
|
|
||||
LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
|
||||
LL + fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'b
|
||||
--> $DIR/needless_lifetimes.rs:63:1
|
||||
--> $DIR/needless_lifetimes.rs:65:1
|
||||
|
|
||||
LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
|
||||
LL + fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:70:1
|
||||
--> $DIR/needless_lifetimes.rs:72:1
|
||||
|
|
||||
LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
|
||||
LL + fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:79:1
|
||||
--> $DIR/needless_lifetimes.rs:81:1
|
||||
|
|
||||
LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
|
||||
LL + fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:84:1
|
||||
--> $DIR/needless_lifetimes.rs:86:1
|
||||
|
|
||||
LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
|
||||
LL + fn where_clause_without_lt<T>(x: &u8, _y: u8) -> Result<&u8, ()>
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a, 'b
|
||||
--> $DIR/needless_lifetimes.rs:96:1
|
||||
--> $DIR/needless_lifetimes.rs:98:1
|
||||
|
|
||||
LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace with `'_` in generic arguments such as here
|
||||
--> $DIR/needless_lifetimes.rs:96:37
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
|
||||
LL + fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {}
|
||||
|
|
||||
LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
|
||||
| ^^
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:120:1
|
||||
--> $DIR/needless_lifetimes.rs:122:1
|
||||
|
|
||||
LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace with `'_` in generic arguments such as here
|
||||
--> $DIR/needless_lifetimes.rs:120:32
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
|
||||
LL + fn fn_bound_2<F, I>(_m: Lt<'_, I>, _f: F) -> Lt<'_, I>
|
||||
|
|
||||
LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
|
||||
| ^^
|
||||
|
||||
error: the following explicit lifetimes could be elided: 's
|
||||
--> $DIR/needless_lifetimes.rs:150:5
|
||||
--> $DIR/needless_lifetimes.rs:152:5
|
||||
|
|
||||
LL | fn self_and_out<'s>(&'s self) -> &'s u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn self_and_out<'s>(&'s self) -> &'s u8 {
|
||||
LL + fn self_and_out(&self) -> &u8 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 't
|
||||
--> $DIR/needless_lifetimes.rs:157:5
|
||||
--> $DIR/needless_lifetimes.rs:159:5
|
||||
|
|
||||
LL | fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
|
||||
LL + fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 's
|
||||
--> $DIR/needless_lifetimes.rs:164:5
|
||||
--> $DIR/needless_lifetimes.rs:166:5
|
||||
|
|
||||
LL | fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
|
||||
LL + fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 's, 't
|
||||
--> $DIR/needless_lifetimes.rs:168:5
|
||||
--> $DIR/needless_lifetimes.rs:170:5
|
||||
|
|
||||
LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
|
||||
LL + fn distinct_self_and_in(&self, _x: &u8) {}
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:187:1
|
||||
--> $DIR/needless_lifetimes.rs:189:1
|
||||
|
|
||||
LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace with `'_` in generic arguments such as here
|
||||
--> $DIR/needless_lifetimes.rs:187:33
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
|
||||
LL + fn struct_with_lt(_foo: Foo<'_>) -> &str {
|
||||
|
|
||||
LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
|
||||
| ^^
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'b
|
||||
--> $DIR/needless_lifetimes.rs:205:1
|
||||
--> $DIR/needless_lifetimes.rs:207:1
|
||||
|
|
||||
LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace with `'_` in generic arguments such as here
|
||||
--> $DIR/needless_lifetimes.rs:205:43
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
|
||||
LL + fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str {
|
||||
|
|
||||
LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
|
||||
| ^^
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:213:1
|
||||
--> $DIR/needless_lifetimes.rs:215:1
|
||||
|
|
||||
LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
|
||||
LL + fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:228:1
|
||||
--> $DIR/needless_lifetimes.rs:230:1
|
||||
|
|
||||
LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
|
||||
LL + fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:234:1
|
||||
--> $DIR/needless_lifetimes.rs:236:1
|
||||
|
|
||||
LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace with `'_` in generic arguments such as here
|
||||
--> $DIR/needless_lifetimes.rs:234:37
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
|
||||
LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
|
||||
|
|
||||
LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
|
||||
| ^^
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'b
|
||||
--> $DIR/needless_lifetimes.rs:252:1
|
||||
--> $DIR/needless_lifetimes.rs:254:1
|
||||
|
|
||||
LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace with `'_` in generic arguments such as here
|
||||
--> $DIR/needless_lifetimes.rs:252:47
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
|
||||
LL + fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str {
|
||||
|
|
||||
LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
|
||||
| ^^
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:260:1
|
||||
--> $DIR/needless_lifetimes.rs:262:1
|
||||
|
|
||||
LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
|
||||
LL + fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:264:1
|
||||
--> $DIR/needless_lifetimes.rs:266:1
|
||||
|
|
||||
LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
|
||||
LL + fn named_input_elided_output(_arg: &str) -> &str {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:272:1
|
||||
--> $DIR/needless_lifetimes.rs:274:1
|
||||
|
|
||||
LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
|
||||
LL + fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:308:1
|
||||
--> $DIR/needless_lifetimes.rs:310:1
|
||||
|
|
||||
LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace with `'_` in generic arguments such as here
|
||||
--> $DIR/needless_lifetimes.rs:308:47
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
|
||||
LL + fn out_return_type_lts(e: &str) -> Cow<'_> {
|
||||
|
|
||||
LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
|
||||
| ^^
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:315:9
|
||||
--> $DIR/needless_lifetimes.rs:317:9
|
||||
|
|
||||
LL | fn needless_lt<'a>(x: &'a u8) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn needless_lt<'a>(x: &'a u8) {}
|
||||
LL + fn needless_lt(x: &u8) {}
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:319:9
|
||||
--> $DIR/needless_lifetimes.rs:321:9
|
||||
|
|
||||
LL | fn needless_lt<'a>(_x: &'a u8) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn needless_lt<'a>(_x: &'a u8) {}
|
||||
LL + fn needless_lt(_x: &u8) {}
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:332:9
|
||||
--> $DIR/needless_lifetimes.rs:334:9
|
||||
|
|
||||
LL | fn baz<'a>(&'a self) -> impl Foo + 'a {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn baz<'a>(&'a self) -> impl Foo + 'a {
|
||||
LL + fn baz(&self) -> impl Foo + '_ {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:364:5
|
||||
--> $DIR/needless_lifetimes.rs:366:5
|
||||
|
|
||||
LL | fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
|
||||
LL + fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&i32) -> &i32) -> &i32 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:373:5
|
||||
--> $DIR/needless_lifetimes.rs:375:5
|
||||
|
|
||||
LL | fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
|
||||
LL + fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:385:5
|
||||
--> $DIR/needless_lifetimes.rs:387:5
|
||||
|
|
||||
LL | fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
|
||||
LL + fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:400:5
|
||||
--> $DIR/needless_lifetimes.rs:402:5
|
||||
|
|
||||
LL | fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
|
||||
LL + fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:413:5
|
||||
--> $DIR/needless_lifetimes.rs:415:5
|
||||
|
|
||||
LL | fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
|
||||
LL + fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:416:5
|
||||
--> $DIR/needless_lifetimes.rs:418:5
|
||||
|
|
||||
LL | fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
|
||||
LL + fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:438:9
|
||||
--> $DIR/needless_lifetimes.rs:440:9
|
||||
|
|
||||
LL | fn implicit<'a>(&'a self) -> &'a () {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn implicit<'a>(&'a self) -> &'a () {
|
||||
LL + fn implicit(&self) -> &() {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:441:9
|
||||
--> $DIR/needless_lifetimes.rs:443:9
|
||||
|
|
||||
LL | fn implicit_mut<'a>(&'a mut self) -> &'a () {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn implicit_mut<'a>(&'a mut self) -> &'a () {
|
||||
LL + fn implicit_mut(&mut self) -> &() {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:452:9
|
||||
--> $DIR/needless_lifetimes.rs:454:9
|
||||
|
|
||||
LL | fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
|
||||
LL + fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:458:9
|
||||
--> $DIR/needless_lifetimes.rs:460:9
|
||||
|
|
||||
LL | fn implicit<'a>(&'a self) -> &'a ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn implicit<'a>(&'a self) -> &'a ();
|
||||
LL + fn implicit(&self) -> &();
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:459:9
|
||||
--> $DIR/needless_lifetimes.rs:461:9
|
||||
|
|
||||
LL | fn implicit_provided<'a>(&'a self) -> &'a () {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn implicit_provided<'a>(&'a self) -> &'a () {
|
||||
LL + fn implicit_provided(&self) -> &() {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:468:9
|
||||
--> $DIR/needless_lifetimes.rs:470:9
|
||||
|
|
||||
LL | fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
|
||||
LL + fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:469:9
|
||||
--> $DIR/needless_lifetimes.rs:471:9
|
||||
|
|
||||
LL | fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:478:5
|
||||
|
|
||||
LL | fn foo<'a>(x: &'a u8, y: &'_ u8) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
|
||||
LL + fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:480:5
|
||||
|
|
||||
LL | fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | fn foo<'a>(x: &'a u8, y: &'_ u8) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn foo<'a>(x: &'a u8, y: &'_ u8) {}
|
||||
LL + fn foo(x: &u8, y: &'_ u8) {}
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:487:5
|
||||
--> $DIR/needless_lifetimes.rs:482:5
|
||||
|
|
||||
LL | fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
|
||||
LL + fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:489:5
|
||||
|
|
||||
LL | fn one_input<'a>(x: &'a u8) -> &'a u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn one_input<'a>(x: &'a u8) -> &'a u8 {
|
||||
LL + fn one_input(x: &u8) -> &u8 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:492:5
|
||||
--> $DIR/needless_lifetimes.rs:494:5
|
||||
|
|
||||
LL | fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
|
||||
LL + fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) -> &'b u8 {
|
||||
|
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a
|
||||
--> $DIR/needless_lifetimes.rs:505:13
|
||||
--> $DIR/needless_lifetimes.rs:507:13
|
||||
|
|
||||
LL | fn one_input<'a>(x: &'a u8) -> &'a u8 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -322,6 +549,11 @@ LL | local_one_input_macro!();
|
||||
| ------------------------ in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `local_one_input_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: elide the lifetimes
|
||||
|
|
||||
LL - fn one_input<'a>(x: &'a u8) -> &'a u8 {
|
||||
LL + fn one_input(x: &u8) -> &u8 {
|
||||
|
|
||||
|
||||
error: aborting due to 46 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user