|
1 |
| -use crate::errors::{ExternCrateNotIdiomatic, UnusedExternCrate}; |
2 |
| -use rustc_data_structures::fx::FxHashMap; |
3 | 1 | use rustc_data_structures::unord::UnordSet;
|
4 |
| -use rustc_hir as hir; |
5 | 2 | use rustc_hir::def::DefKind;
|
6 |
| -use rustc_hir::def_id::{DefId, LocalDefId}; |
| 3 | +use rustc_hir::def_id::LocalDefId; |
7 | 4 | use rustc_middle::ty::TyCtxt;
|
8 | 5 | use rustc_session::lint;
|
9 |
| -use rustc_span::{Span, Symbol}; |
10 | 6 |
|
11 | 7 | pub fn check_crate(tcx: TyCtxt<'_>) {
|
12 | 8 | let mut used_trait_imports: UnordSet<LocalDefId> = Default::default();
|
@@ -43,131 +39,4 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
43 | 39 | |lint| lint,
|
44 | 40 | );
|
45 | 41 | }
|
46 |
| - |
47 |
| - unused_crates_lint(tcx); |
48 |
| -} |
49 |
| - |
50 |
| -fn unused_crates_lint(tcx: TyCtxt<'_>) { |
51 |
| - let lint = lint::builtin::UNUSED_EXTERN_CRATES; |
52 |
| - |
53 |
| - // Collect first the crates that are completely unused. These we |
54 |
| - // can always suggest removing (no matter which edition we are |
55 |
| - // in). |
56 |
| - let unused_extern_crates: FxHashMap<LocalDefId, Span> = tcx |
57 |
| - .maybe_unused_extern_crates(()) |
58 |
| - .iter() |
59 |
| - .filter(|&&(def_id, _)| { |
60 |
| - tcx.extern_mod_stmt_cnum(def_id).map_or(true, |cnum| { |
61 |
| - !tcx.is_compiler_builtins(cnum) |
62 |
| - && !tcx.is_panic_runtime(cnum) |
63 |
| - && !tcx.has_global_allocator(cnum) |
64 |
| - && !tcx.has_panic_handler(cnum) |
65 |
| - }) |
66 |
| - }) |
67 |
| - .cloned() |
68 |
| - .collect(); |
69 |
| - |
70 |
| - // Collect all the extern crates (in a reliable order). |
71 |
| - let mut crates_to_lint = vec![]; |
72 |
| - |
73 |
| - for id in tcx.hir().items() { |
74 |
| - if matches!(tcx.def_kind(id.owner_id), DefKind::ExternCrate) { |
75 |
| - let item = tcx.hir().item(id); |
76 |
| - if let hir::ItemKind::ExternCrate(orig_name) = item.kind { |
77 |
| - crates_to_lint.push(ExternCrateToLint { |
78 |
| - def_id: item.owner_id.to_def_id(), |
79 |
| - span: item.span, |
80 |
| - orig_name, |
81 |
| - warn_if_unused: !item.ident.as_str().starts_with('_'), |
82 |
| - }); |
83 |
| - } |
84 |
| - } |
85 |
| - } |
86 |
| - |
87 |
| - let extern_prelude = &tcx.resolutions(()).extern_prelude; |
88 |
| - |
89 |
| - for extern_crate in &crates_to_lint { |
90 |
| - let def_id = extern_crate.def_id.expect_local(); |
91 |
| - let item = tcx.hir().expect_item(def_id); |
92 |
| - |
93 |
| - // If the crate is fully unused, we suggest removing it altogether. |
94 |
| - // We do this in any edition. |
95 |
| - if extern_crate.warn_if_unused { |
96 |
| - if let Some(&span) = unused_extern_crates.get(&def_id) { |
97 |
| - // Removal suggestion span needs to include attributes (Issue #54400) |
98 |
| - let id = tcx.hir().local_def_id_to_hir_id(def_id); |
99 |
| - let span_with_attrs = tcx |
100 |
| - .hir() |
101 |
| - .attrs(id) |
102 |
| - .iter() |
103 |
| - .map(|attr| attr.span) |
104 |
| - .fold(span, |acc, attr_span| acc.to(attr_span)); |
105 |
| - |
106 |
| - tcx.emit_spanned_lint(lint, id, span, UnusedExternCrate { span: span_with_attrs }); |
107 |
| - continue; |
108 |
| - } |
109 |
| - } |
110 |
| - |
111 |
| - // If we are not in Rust 2018 edition, then we don't make any further |
112 |
| - // suggestions. |
113 |
| - if !tcx.sess.rust_2018() { |
114 |
| - continue; |
115 |
| - } |
116 |
| - |
117 |
| - // If the extern crate isn't in the extern prelude, |
118 |
| - // there is no way it can be written as a `use`. |
119 |
| - let orig_name = extern_crate.orig_name.unwrap_or(item.ident.name); |
120 |
| - if !extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) { |
121 |
| - continue; |
122 |
| - } |
123 |
| - |
124 |
| - // If the extern crate is renamed, then we cannot suggest replacing it with a use as this |
125 |
| - // would not insert the new name into the prelude, where other imports in the crate may be |
126 |
| - // expecting it. |
127 |
| - if extern_crate.orig_name.is_some() { |
128 |
| - continue; |
129 |
| - } |
130 |
| - |
131 |
| - let id = tcx.hir().local_def_id_to_hir_id(def_id); |
132 |
| - // If the extern crate has any attributes, they may have funky |
133 |
| - // semantics we can't faithfully represent using `use` (most |
134 |
| - // notably `#[macro_use]`). Ignore it. |
135 |
| - if !tcx.hir().attrs(id).is_empty() { |
136 |
| - continue; |
137 |
| - } |
138 |
| - |
139 |
| - let base_replacement = match extern_crate.orig_name { |
140 |
| - Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name), |
141 |
| - None => format!("use {};", item.ident.name), |
142 |
| - }; |
143 |
| - let vis = tcx.sess.source_map().span_to_snippet(item.vis_span).unwrap_or_default(); |
144 |
| - let add_vis = |to| if vis.is_empty() { to } else { format!("{} {}", vis, to) }; |
145 |
| - tcx.emit_spanned_lint( |
146 |
| - lint, |
147 |
| - id, |
148 |
| - extern_crate.span, |
149 |
| - ExternCrateNotIdiomatic { |
150 |
| - span: extern_crate.span, |
151 |
| - msg_code: add_vis("use".to_string()), |
152 |
| - suggestion_code: add_vis(base_replacement), |
153 |
| - }, |
154 |
| - ); |
155 |
| - } |
156 |
| -} |
157 |
| - |
158 |
| -struct ExternCrateToLint { |
159 |
| - /// `DefId` of the extern crate |
160 |
| - def_id: DefId, |
161 |
| - |
162 |
| - /// span from the item |
163 |
| - span: Span, |
164 |
| - |
165 |
| - /// if `Some`, then this is renamed (`extern crate orig_name as |
166 |
| - /// crate_name`), and -- perhaps surprisingly -- this stores the |
167 |
| - /// *original* name (`item.name` will contain the new name) |
168 |
| - orig_name: Option<Symbol>, |
169 |
| - |
170 |
| - /// if `false`, the original name started with `_`, so we shouldn't lint |
171 |
| - /// about it going unused (but we should still emit idiom lints). |
172 |
| - warn_if_unused: bool, |
173 | 42 | }
|
0 commit comments