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;
10 /// **What it does:** Checks for imports ending in `::{self}`.
12 /// **Why is this bad?** In most cases, this can be written much more cleanly by omitting `::{self}`.
14 /// **Known problems:** Removing `::{self}` will cause any non-module items at the same path to also be imported.
15 /// This might cause a naming conflict (https://github.com/rust-lang/rustfmt/issues/3568). This lint makes no attempt
16 /// to detect this scenario and that is why it is a restriction lint.
21 /// use std::io::{self};
27 pub UNNECESSARY_SELF_IMPORTS,
29 "imports ending in `::{self}`, which can be omitted"
32 declare_lint_pass!(UnnecessarySelfImports => [UNNECESSARY_SELF_IMPORTS]);
34 impl EarlyLintPass for UnnecessarySelfImports {
35 fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
37 if let ItemKind::Use(use_tree) = &item.kind;
38 if let UseTreeKind::Nested(nodes) = &use_tree.kind;
39 if let [(self_tree, _)] = &**nodes;
40 if let [self_seg] = &*self_tree.prefix.segments;
41 if self_seg.ident.name == kw::SelfLower;
42 if let Some(last_segment) = use_tree.prefix.segments.last();
47 UNNECESSARY_SELF_IMPORTS,
49 "import ending with `::{self}`",
52 last_segment.span().with_hi(item.span.hi()),
53 "consider omitting `::{self}`",
57 if let UseTreeKind::Simple(Some(alias), ..) = self_tree.kind { format!(" as {}", alias) } else { String::new() },
59 Applicability::MaybeIncorrect,
61 diag.note("this will slightly change semantics; any non-module items at the same path will also be imported");