1 use clippy_utils::diagnostics::span_lint_and_then;
2 use if_chain::if_chain;
3 use rustc_ast::{Item, ItemKind, UseTreeKind};
4 use rustc_errors::Applicability;
5 use rustc_lint::{EarlyContext, EarlyLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
7 use rustc_span::symbol::kw;
11 /// Checks for imports ending in `::{self}`.
13 /// ### Why is this bad?
14 /// In most cases, this can be written much more cleanly by omitting `::{self}`.
16 /// ### Known problems
17 /// Removing `::{self}` will cause any non-module items at the same path to also be imported.
18 /// This might cause a naming conflict (https://github.com/rust-lang/rustfmt/issues/3568). This lint makes no attempt
19 /// to detect this scenario and that is why it is a restriction lint.
23 /// use std::io::{self};
29 #[clippy::version = "1.53.0"]
30 pub UNNECESSARY_SELF_IMPORTS,
32 "imports ending in `::{self}`, which can be omitted"
35 declare_lint_pass!(UnnecessarySelfImports => [UNNECESSARY_SELF_IMPORTS]);
37 impl EarlyLintPass for UnnecessarySelfImports {
38 fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
40 if let ItemKind::Use(use_tree) = &item.kind;
41 if let UseTreeKind::Nested(nodes) = &use_tree.kind;
42 if let [(self_tree, _)] = &**nodes;
43 if let [self_seg] = &*self_tree.prefix.segments;
44 if self_seg.ident.name == kw::SelfLower;
45 if let Some(last_segment) = use_tree.prefix.segments.last();
50 UNNECESSARY_SELF_IMPORTS,
52 "import ending with `::{self}`",
55 last_segment.span().with_hi(item.span.hi()),
56 "consider omitting `::{self}`",
60 if let UseTreeKind::Simple(Some(alias), ..) = self_tree.kind { format!(" as {}", alias) } else { String::new() },
62 Applicability::MaybeIncorrect,
64 diag.note("this will slightly change semantics; any non-module items at the same path will also be imported");