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 pub UNNECESSARY_SELF_IMPORTS,
31 "imports ending in `::{self}`, which can be omitted"
34 declare_lint_pass!(UnnecessarySelfImports => [UNNECESSARY_SELF_IMPORTS]);
36 impl EarlyLintPass for UnnecessarySelfImports {
37 fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
39 if let ItemKind::Use(use_tree) = &item.kind;
40 if let UseTreeKind::Nested(nodes) = &use_tree.kind;
41 if let [(self_tree, _)] = &**nodes;
42 if let [self_seg] = &*self_tree.prefix.segments;
43 if self_seg.ident.name == kw::SelfLower;
44 if let Some(last_segment) = use_tree.prefix.segments.last();
49 UNNECESSARY_SELF_IMPORTS,
51 "import ending with `::{self}`",
54 last_segment.span().with_hi(item.span.hi()),
55 "consider omitting `::{self}`",
59 if let UseTreeKind::Simple(Some(alias), ..) = self_tree.kind { format!(" as {}", alias) } else { String::new() },
61 Applicability::MaybeIncorrect,
63 diag.note("this will slightly change semantics; any non-module items at the same path will also be imported");