summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/check_unused.rs
blob: f3f5851d8f92cab6977cc1029695d11c4db5a091 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
use rustc_data_structures::unord::UnordSet;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint;

pub fn check_crate(tcx: TyCtxt<'_>) {
    let mut used_trait_imports: UnordSet<LocalDefId> = Default::default();

    for item_def_id in tcx.hir().body_owners() {
        let imports = tcx.used_trait_imports(item_def_id);
        debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
        used_trait_imports.extend(imports.items().copied());
    }

    for &id in tcx.maybe_unused_trait_imports(()) {
        debug_assert_eq!(tcx.def_kind(id), DefKind::Use);
        if tcx.visibility(id).is_public() {
            continue;
        }
        if used_trait_imports.contains(&id) {
            continue;
        }
        let item = tcx.hir().expect_item(id);
        if item.span.is_dummy() {
            continue;
        }
        let (path, _) = item.expect_use();
        let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
            format!("unused import: `{}`", snippet)
        } else {
            "unused import".to_owned()
        };
        tcx.struct_span_lint_hir(
            lint::builtin::UNUSED_IMPORTS,
            item.hir_id(),
            path.span,
            msg,
            |lint| lint,
        );
    }
}