Skip to content

Commit 2ece8ea

Browse files
committed
Start reimplement
1 parent 3a14911 commit 2ece8ea

File tree

1 file changed

+95
-18
lines changed

1 file changed

+95
-18
lines changed

clippy_lints/src/std_instead_of_core.rs

Lines changed: 95 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
use std::hash::{Hash, Hasher};
12
use clippy_utils::diagnostics::span_lint_and_sugg;
23
use clippy_utils::is_from_proc_macro;
4+
use rustc_data_structures::fx::FxIndexSet;
35
use rustc_errors::Applicability;
46
use rustc_hir::def::Res;
57
use rustc_hir::def_id::DefId;
6-
use rustc_hir::{HirId, Path, PathSegment};
8+
use rustc_hir::{HirId, Item, ItemKind, Path, PathSegment, UseKind};
79
use rustc_lint::{LateContext, LateLintPass, LintContext};
810
use rustc_middle::lint::in_external_macro;
911
use rustc_session::impl_lint_pass;
@@ -93,9 +95,47 @@ pub struct StdReexports {
9395
// twice. First for the mod, second for the macro. This is used to avoid the lint reporting for the macro
9496
// when the path could be also be used to access the module.
9597
prev_span: Span,
98+
open_use: Option<OpenUseSpan>
9699
}
100+
97101
impl_lint_pass!(StdReexports => [STD_INSTEAD_OF_CORE, STD_INSTEAD_OF_ALLOC, ALLOC_INSTEAD_OF_CORE]);
98102

103+
#[derive(Debug)]
104+
struct OpenUseSpan {
105+
container: Span,
106+
members: FxIndexSet<UseSpanMember>
107+
}
108+
109+
#[derive(Debug, Copy, Clone)]
110+
struct UseSpanMember {
111+
inner: Span,
112+
lint_data: LintData,
113+
}
114+
115+
impl PartialEq for UseSpanMember {
116+
fn eq(&self, other: &Self) -> bool {
117+
self.inner.eq(&other.inner)
118+
}
119+
}
120+
121+
impl Eq for UseSpanMember {}
122+
123+
impl Hash for UseSpanMember {
124+
fn hash<H: Hasher>(&self, state: &mut H) {
125+
self.inner.hash(state);
126+
}
127+
}
128+
129+
#[derive(Debug, Copy, Clone)]
130+
enum LintData {
131+
CanReplace {
132+
lint: &'static crate::Lint,
133+
used_mod: &'static str,
134+
replace_with: &'static str,
135+
},
136+
NoReplace,
137+
}
138+
99139
impl<'tcx> LateLintPass<'tcx> for StdReexports {
100140
fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) {
101141
if let Res::Def(_, def_id) = path.res
@@ -104,37 +144,74 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
104144
&& !in_external_macro(cx.sess(), path.span)
105145
&& !is_from_proc_macro(cx, &first_segment.ident)
106146
{
107-
let (lint, used_mod, replace_with) = match first_segment.ident.name {
147+
let lint_data = match first_segment.ident.name {
108148
sym::std => match cx.tcx.crate_name(def_id.krate) {
109-
sym::core => (STD_INSTEAD_OF_CORE, "std", "core"),
110-
sym::alloc => (STD_INSTEAD_OF_ALLOC, "std", "alloc"),
149+
sym::core => LintData::CanReplace {
150+
lint: STD_INSTEAD_OF_CORE,
151+
used_mod: "std",
152+
replace_with: "core",
153+
},
154+
sym::alloc => LintData::CanReplace {
155+
lint: STD_INSTEAD_OF_ALLOC,
156+
used_mod: "std",
157+
replace_with: "alloc",
158+
},
111159
_ => {
112160
self.prev_span = first_segment.ident.span;
113-
return;
161+
LintData::NoReplace
114162
},
115163
},
116164
sym::alloc => {
117165
if cx.tcx.crate_name(def_id.krate) == sym::core {
118-
(ALLOC_INSTEAD_OF_CORE, "alloc", "core")
166+
LintData::CanReplace {
167+
lint: ALLOC_INSTEAD_OF_CORE,
168+
used_mod: "alloc",
169+
replace_with: "core",
170+
}
119171
} else {
120172
self.prev_span = first_segment.ident.span;
121-
return;
173+
LintData::NoReplace
122174
}
123175
},
124176
_ => return,
125177
};
126-
if first_segment.ident.span != self.prev_span {
127-
span_lint_and_sugg(
128-
cx,
129-
lint,
130-
first_segment.ident.span,
131-
&format!("used import from `{used_mod}` instead of `{replace_with}`"),
132-
&format!("consider importing the item from `{replace_with}`"),
133-
replace_with.to_string(),
134-
Applicability::MachineApplicable,
135-
);
136-
self.prev_span = first_segment.ident.span;
178+
if let Some(in_use) = self.open_use.as_mut() {
179+
in_use.members.insert(UseSpanMember {
180+
inner: path.span,
181+
lint_data,
182+
});
183+
return;
137184
}
185+
if let LintData::CanReplace { lint, used_mod, replace_with } = lint_data {
186+
if first_segment.ident.span != self.prev_span {
187+
span_lint_and_sugg(
188+
cx,
189+
lint,
190+
first_segment.ident.span,
191+
&format!("used import from `{used_mod}` instead of `{replace_with}`"),
192+
&format!("consider importing the item from `{replace_with}`"),
193+
replace_with.to_string(),
194+
Applicability::MachineApplicable,
195+
);
196+
self.prev_span = first_segment.ident.span;
197+
}
198+
}
199+
}
200+
}
201+
202+
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
203+
if matches!(item.kind, ItemKind::Use(_, UseKind::ListStem)) {
204+
self.open_use = Some(OpenUseSpan {
205+
container: item.span,
206+
members: FxIndexSet::default(),
207+
})
208+
}
209+
210+
}
211+
212+
fn check_item_post(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
213+
if let Some(collected_use) = self.open_use.take() {
214+
138215
}
139216
}
140217
}

0 commit comments

Comments
 (0)