+impl<'tcx> LateLintPass<'tcx> for UseSelf {
+ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+ // We push the self types of `impl`s on a stack here. Only the top type on the stack is
+ // relevant for linting, since this is the self type of the `impl` we're currently in. To
+ // avoid linting on nested items, we push `StackItem::NoCheck` on the stack to signal, that
+ // we're in an `impl` or nested item, that we don't want to lint
+ //
+ // NB: If you push something on the stack in this method, remember to also pop it in the
+ // `check_item_post` method.
+ match &item.kind {
+ ItemKind::Impl(Impl {
+ self_ty: hir_self_ty,
+ of_trait,
+ ..
+ }) => {
+ let should_check = if let TyKind::Path(QPath::Resolved(_, ref item_path)) = hir_self_ty.kind {
+ let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
+ parameters.as_ref().map_or(true, |params| {
+ !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
+ })
+ } else {
+ false
+ };
+ let impl_trait_ref_def_id = of_trait.as_ref().map(|_| cx.tcx.hir().local_def_id(item.hir_id()));
+ if should_check {
+ self.stack.push(StackItem::Check {
+ hir_id: hir_self_ty.hir_id,
+ impl_trait_ref_def_id,
+ types_to_lint: Vec::new(),
+ types_to_skip: Vec::new(),
+ });
+ } else {
+ self.stack.push(StackItem::NoCheck);
+ }
+ },
+ ItemKind::Static(..)
+ | ItemKind::Const(..)
+ | ItemKind::Fn(..)
+ | ItemKind::Enum(..)
+ | ItemKind::Struct(..)
+ | ItemKind::Union(..)
+ | ItemKind::Trait(..) => {
+ self.stack.push(StackItem::NoCheck);
+ },
+ _ => (),
+ }
+ }
+
+ fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) {
+ use ItemKind::{Const, Enum, Fn, Impl, Static, Struct, Trait, Union};
+ match item.kind {
+ Impl { .. } | Static(..) | Const(..) | Fn(..) | Enum(..) | Struct(..) | Union(..) | Trait(..) => {
+ self.stack.pop();
+ },
+ _ => (),
+ }
+ }