Skip to content

Commit

Permalink
skip callee visits to avoid invisible-lifetime lint false-positive
Browse files Browse the repository at this point in the history
As far as the higher intermediate representation is concerned,
associated functions like `Ref::clone` are equivalent to the universal
function call syntax expression `<Ref>::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.
  • Loading branch information
zackmdavis committed Jul 15, 2018
1 parent 22c4f56 commit 7c4e9d4
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 3 deletions.
19 changes: 16 additions & 3 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/in-band-lifetimes/elided-lifetimes.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
1 change: 1 addition & 0 deletions src/test/ui/in-band-lifetimes/elided-lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

0 comments on commit 7c4e9d4

Please sign in to comment.