Skip to content

Commit ee3da1b

Browse files
borsJarcho
authored andcommitted
Auto merge of rust-lang#13168 - Alexendoo:std-instead-of-core-msrv, r=Manishearth
Make `std_instead_of_core` somewhat MSRV aware For rust-lang#13158, this catches some things e.g. `core::net` and the recently stable `core::error` but not things moved individually like `UnwindSafe`, as far as I can see the version for those isn't easily available Beta nominating since ideally we'd get this change in the same version as `core::error` becomes stable cc `@kpreid` changelog: none
1 parent 4a19353 commit ee3da1b

File tree

5 files changed

+83
-20
lines changed

5 files changed

+83
-20
lines changed

src/tools/clippy/clippy_lints/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
10341034
allow_comparison_to_zero,
10351035
))
10361036
});
1037-
store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default());
1037+
store.register_late_pass(move |_| Box::new(std_instead_of_core::StdReexports::new(conf)));
10381038
store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv())));
10391039
store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));
10401040
store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(msrv())));

src/tools/clippy/clippy_lints/src/std_instead_of_core.rs

+43-10
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
use clippy_config::msrvs::Msrv;
2+
use clippy_config::Conf;
13
use clippy_utils::diagnostics::span_lint_and_sugg;
24
use clippy_utils::is_from_proc_macro;
5+
use rustc_attr::{StabilityLevel, StableSince};
36
use rustc_errors::Applicability;
47
use rustc_hir::def::Res;
58
use rustc_hir::def_id::DefId;
69
use rustc_hir::{HirId, Path, PathSegment};
710
use rustc_lint::{LateContext, LateLintPass, LintContext};
811
use rustc_middle::lint::in_external_macro;
12+
use rustc_semver::RustcVersion;
913
use rustc_session::impl_lint_pass;
1014
use rustc_span::symbol::kw;
1115
use rustc_span::{sym, Span};
@@ -66,6 +70,10 @@ declare_clippy_lint! {
6670
/// imported from core to ensure disabling `alloc` does not cause the crate to fail to compile. This lint
6771
/// is also useful for crates migrating to become `no_std` compatible.
6872
///
73+
/// ### Known problems
74+
/// The lint is only partially aware of the required MSRV for items that were originally in `std` but moved
75+
/// to `core`.
76+
///
6977
/// ### Example
7078
/// ```no_run
7179
/// # extern crate alloc;
@@ -81,20 +89,30 @@ declare_clippy_lint! {
8189
"type is imported from alloc when available in core"
8290
}
8391

84-
#[derive(Default)]
8592
pub struct StdReexports {
8693
// Paths which can be either a module or a macro (e.g. `std::env`) will cause this check to happen
8794
// twice. First for the mod, second for the macro. This is used to avoid the lint reporting for the macro
8895
// when the path could be also be used to access the module.
8996
prev_span: Span,
97+
msrv: Msrv,
98+
}
99+
100+
impl StdReexports {
101+
pub fn new(conf: &'static Conf) -> Self {
102+
Self {
103+
prev_span: Span::default(),
104+
msrv: conf.msrv.clone(),
105+
}
106+
}
90107
}
108+
91109
impl_lint_pass!(StdReexports => [STD_INSTEAD_OF_CORE, STD_INSTEAD_OF_ALLOC, ALLOC_INSTEAD_OF_CORE]);
92110

93111
impl<'tcx> LateLintPass<'tcx> for StdReexports {
94112
fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) {
95113
if let Res::Def(_, def_id) = path.res
96114
&& let Some(first_segment) = get_first_segment(path)
97-
&& is_stable(cx, def_id)
115+
&& is_stable(cx, def_id, &self.msrv)
98116
&& !in_external_macro(cx.sess(), path.span)
99117
&& !is_from_proc_macro(cx, &first_segment.ident)
100118
{
@@ -131,6 +149,8 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
131149
}
132150
}
133151
}
152+
153+
extract_msrv_attr!(LateContext);
134154
}
135155

136156
/// Returns the first named segment of a [`Path`].
@@ -146,16 +166,29 @@ fn get_first_segment<'tcx>(path: &Path<'tcx>) -> Option<&'tcx PathSegment<'tcx>>
146166
}
147167
}
148168

149-
/// Checks if all ancestors of `def_id` are stable, to avoid linting
150-
/// [unstable moves](https://github.com/rust-lang/rust/pull/95956)
151-
fn is_stable(cx: &LateContext<'_>, mut def_id: DefId) -> bool {
169+
/// Checks if all ancestors of `def_id` meet `msrv` to avoid linting [unstable moves](https://github.com/rust-lang/rust/pull/95956)
170+
/// or now stable moves that were once unstable.
171+
///
172+
/// Does not catch individually moved items
173+
fn is_stable(cx: &LateContext<'_>, mut def_id: DefId, msrv: &Msrv) -> bool {
152174
loop {
153-
if cx
154-
.tcx
155-
.lookup_stability(def_id)
156-
.map_or(false, |stability| stability.is_unstable())
175+
if let Some(stability) = cx.tcx.lookup_stability(def_id)
176+
&& let StabilityLevel::Stable {
177+
since,
178+
allowed_through_unstable_modules: false,
179+
} = stability.level
157180
{
158-
return false;
181+
let stable = match since {
182+
StableSince::Version(v) => {
183+
msrv.meets(RustcVersion::new(v.major.into(), v.minor.into(), v.patch.into()))
184+
},
185+
StableSince::Current => msrv.current().is_none(),
186+
StableSince::Err => false,
187+
};
188+
189+
if !stable {
190+
return false;
191+
}
159192
}
160193

161194
match cx.tcx.opt_parent(def_id) {

src/tools/clippy/tests/ui/std_instead_of_core.fixed

+13-4
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,17 @@ mod std_in_proc_macro_derive {
7575
struct B {}
7676
}
7777

78-
fn main() {
79-
std_instead_of_core();
80-
std_instead_of_alloc();
81-
alloc_instead_of_core();
78+
// Some intrinsics are usable on stable but live in an unstable module, but should still suggest
79+
// replacing std -> core
80+
fn intrinsic(a: *mut u8, b: *mut u8) {
81+
unsafe {
82+
core::intrinsics::copy(a, b, 1);
83+
//~^ std_instead_of_core
84+
}
8285
}
86+
87+
#[clippy::msrv = "1.76"]
88+
fn msrv_1_76(_: std::net::IpAddr) {}
89+
90+
#[clippy::msrv = "1.77"]
91+
fn msrv_1_77(_: core::net::IpAddr) {}

src/tools/clippy/tests/ui/std_instead_of_core.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,17 @@ mod std_in_proc_macro_derive {
7575
struct B {}
7676
}
7777

78-
fn main() {
79-
std_instead_of_core();
80-
std_instead_of_alloc();
81-
alloc_instead_of_core();
78+
// Some intrinsics are usable on stable but live in an unstable module, but should still suggest
79+
// replacing std -> core
80+
fn intrinsic(a: *mut u8, b: *mut u8) {
81+
unsafe {
82+
std::intrinsics::copy(a, b, 1);
83+
//~^ std_instead_of_core
84+
}
8285
}
86+
87+
#[clippy::msrv = "1.76"]
88+
fn msrv_1_76(_: std::net::IpAddr) {}
89+
90+
#[clippy::msrv = "1.77"]
91+
fn msrv_1_77(_: std::net::IpAddr) {}

src/tools/clippy/tests/ui/std_instead_of_core.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,17 @@ LL | use alloc::slice::from_ref;
8585
= note: `-D clippy::alloc-instead-of-core` implied by `-D warnings`
8686
= help: to override `-D warnings` add `#[allow(clippy::alloc_instead_of_core)]`
8787

88-
error: aborting due to 13 previous errors
88+
error: used import from `std` instead of `core`
89+
--> tests/ui/std_instead_of_core.rs:82:9
90+
|
91+
LL | std::intrinsics::copy(a, b, 1);
92+
| ^^^ help: consider importing the item from `core`: `core`
93+
94+
error: used import from `std` instead of `core`
95+
--> tests/ui/std_instead_of_core.rs:91:17
96+
|
97+
LL | fn msrv_1_77(_: std::net::IpAddr) {}
98+
| ^^^ help: consider importing the item from `core`: `core`
99+
100+
error: aborting due to 15 previous errors
89101

0 commit comments

Comments
 (0)