From 7c4e9d4cd805becc3cfa8f06165a615b36baf7bd Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 14 Jul 2018 16:30:18 -0700 Subject: [PATCH] skip callee visits to avoid invisible-lifetime lint false-positive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As far as the higher intermediate representation is concerned, associated functions like `Ref::clone` are equivalent to the universal function call syntax expression `::clone`, so our strategy of linting for invisible lifetimes while visiting types in the LifetimeContext visitor was resulting in us suggesting that the user call `Ref<'_>::clone` (which doesn't parse). It is not without some sentiments of inadequacy that the present author can't think of a better way to avoid this than making the visitor avoid traversing into the callee of call expressions. This should be OK because—one is pretty sure—there aren't going to be lifetimes to resolve in a callee expression. Besides linting for invisible lifetimes (introduced in this branch), the only other work taking place in the `hir::TyPath(hir::QPath::Resolved(None, ref path))` arm of the `visit_ty` method is about resolving lifetimes in existential types. This is all about issue no. 52041. --- src/librustc/middle/resolve_lifetime.rs | 19 ++++++++++++++++--- .../in-band-lifetimes/elided-lifetimes.fixed | 1 + .../ui/in-band-lifetimes/elided-lifetimes.rs | 1 + 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 7c6718f3d065e..a4592d9482f6a 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -564,6 +564,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { + if let hir::ExprCall(_, ref arguments) = expr.node { + // Avoid traversing into a call expression's callee specifically to avoid + // triggering a false positive for the invisible-lifetimes-in-type-paths lint. (The + // motivating examples were `Ref::map` and `Ref::clone`.) + // FIXME: is there a more elegant way of doing this?! + // + // But do visit the arguments + walk_list!(self, visit_expr, arguments); + } else { + intravisit::walk_expr(self, expr); + } + } + fn visit_ty(&mut self, ty: &'tcx hir::Ty) { debug!("visit_ty: id={:?} ty={:?}", ty.id, ty); match ty.node { @@ -2136,9 +2150,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { err.span_suggestion_with_applicability( replace_span, "indicate the anonymous lifetime", - suggestion.to_owned(), - // false positives observed with macros, `Ref::map` (tracking issue #52041) - Applicability::MaybeIncorrect + suggestion, + Applicability::MachineApplicable ); } err.emit(); diff --git a/src/test/ui/in-band-lifetimes/elided-lifetimes.fixed b/src/test/ui/in-band-lifetimes/elided-lifetimes.fixed index 24df541b08fe0..5d82cc8fd939a 100644 --- a/src/test/ui/in-band-lifetimes/elided-lifetimes.fixed +++ b/src/test/ui/in-band-lifetimes/elided-lifetimes.fixed @@ -51,4 +51,5 @@ fn main() { let loyalty: Ref<'_, (u32, char)> = honesty.borrow(); //~^ ERROR implicit lifetime parameters in types are deprecated //~| HELP indicate the anonymous lifetime + let generosity = Ref::map(loyalty, |t| &t.0); } diff --git a/src/test/ui/in-band-lifetimes/elided-lifetimes.rs b/src/test/ui/in-band-lifetimes/elided-lifetimes.rs index 661dd7530b723..b0158b8b3f484 100644 --- a/src/test/ui/in-band-lifetimes/elided-lifetimes.rs +++ b/src/test/ui/in-band-lifetimes/elided-lifetimes.rs @@ -51,4 +51,5 @@ fn main() { let loyalty: Ref<(u32, char)> = honesty.borrow(); //~^ ERROR implicit lifetime parameters in types are deprecated //~| HELP indicate the anonymous lifetime + let generosity = Ref::map(loyalty, |t| &t.0); }