Skip to content

Commit c9f0d1a

Browse files
committed
Auto merge of #9103 - i509VCB:std-instead-of-core, r=Manishearth
Add `std_instead_of_core`, `std_instead_of_alloc`, `alloc_instead_of_core` Closes #7724 Introduces 3 new lints: - `std_instead_of_core` - lints items resolved through `std` which are available in `core` - `std_instead_of_alloc` - lints items resolved through `std` which are available in `alloc` - `alloc_instead_of_core` - lints items resolved through `alloc` which are available in `core` Though the original issue only mentions `std_instead_of_alloc`, the other two lints could be useful as well. questions: - what do I call the file the lints live in? I was thinking `std_reexports`? changelog: new lint's: [`std_instead_of_core`], [`std_instead_of_alloc`], [`alloc_instead_of_core`]
2 parents 0f5a38f + 2f825db commit c9f0d1a

7 files changed

+269
-0
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -3432,6 +3432,7 @@ Released 2018-09-13
34323432
<!-- lint disable no-unused-definitions -->
34333433
<!-- begin autogenerated links to lint list -->
34343434
[`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons
3435+
[`alloc_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#alloc_instead_of_core
34353436
[`allow_attributes_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason
34363437
[`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range
34373438
[`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
@@ -3901,6 +3902,8 @@ Released 2018-09-13
39013902
[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
39023903
[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
39033904
[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
3905+
[`std_instead_of_alloc`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_alloc
3906+
[`std_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_core
39043907
[`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string
39053908
[`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add
39063909
[`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign

clippy_lints/src/lib.register_lints.rs

+3
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,9 @@ store.register_lints(&[
497497
size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
498498
slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
499499
stable_sort_primitive::STABLE_SORT_PRIMITIVE,
500+
std_instead_of_core::ALLOC_INSTEAD_OF_CORE,
501+
std_instead_of_core::STD_INSTEAD_OF_ALLOC,
502+
std_instead_of_core::STD_INSTEAD_OF_CORE,
500503
strings::STRING_ADD,
501504
strings::STRING_ADD_ASSIGN,
502505
strings::STRING_FROM_UTF8_AS_BYTES,

clippy_lints/src/lib.register_restriction.rs

+3
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
6666
LintId::of(shadow::SHADOW_SAME),
6767
LintId::of(shadow::SHADOW_UNRELATED),
6868
LintId::of(single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES),
69+
LintId::of(std_instead_of_core::ALLOC_INSTEAD_OF_CORE),
70+
LintId::of(std_instead_of_core::STD_INSTEAD_OF_ALLOC),
71+
LintId::of(std_instead_of_core::STD_INSTEAD_OF_CORE),
6972
LintId::of(strings::STRING_ADD),
7073
LintId::of(strings::STRING_SLICE),
7174
LintId::of(strings::STRING_TO_STRING),

clippy_lints/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ mod single_component_path_imports;
365365
mod size_of_in_element_count;
366366
mod slow_vector_initialization;
367367
mod stable_sort_primitive;
368+
mod std_instead_of_core;
368369
mod strings;
369370
mod strlen_on_c_strings;
370371
mod suspicious_operation_groupings;
@@ -915,6 +916,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
915916
let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
916917
store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
917918
store.register_late_pass(|| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
919+
store.register_late_pass(|| Box::new(std_instead_of_core::StdReexports));
918920
// add lints here, do not remove this comment, it's used in `new_lint`
919921
}
920922

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
use clippy_utils::diagnostics::span_lint_and_help;
2+
use rustc_hir::{def::Res, HirId, Path, PathSegment};
3+
use rustc_lint::{LateContext, LateLintPass, Lint};
4+
use rustc_session::{declare_lint_pass, declare_tool_lint};
5+
use rustc_span::{sym, symbol::kw, Symbol};
6+
7+
declare_clippy_lint! {
8+
/// ### What it does
9+
///
10+
/// Finds items imported through `std` when available through `core`.
11+
///
12+
/// ### Why is this bad?
13+
///
14+
/// Crates which have `no_std` compatibility may wish to ensure types are imported from core to ensure
15+
/// disabling `std` does not cause the crate to fail to compile. This lint is also useful for crates
16+
/// migrating to become `no_std` compatible.
17+
///
18+
/// ### Example
19+
/// ```rust
20+
/// use std::hash::Hasher;
21+
/// ```
22+
/// Use instead:
23+
/// ```rust
24+
/// use core::hash::Hasher;
25+
/// ```
26+
#[clippy::version = "1.64.0"]
27+
pub STD_INSTEAD_OF_CORE,
28+
restriction,
29+
"type is imported from std when available in core"
30+
}
31+
32+
declare_clippy_lint! {
33+
/// ### What it does
34+
///
35+
/// Finds items imported through `std` when available through `alloc`.
36+
///
37+
/// ### Why is this bad?
38+
///
39+
/// Crates which have `no_std` compatibility and require alloc may wish to ensure types are imported from
40+
/// alloc to ensure disabling `std` does not cause the crate to fail to compile. This lint is also useful
41+
/// for crates migrating to become `no_std` compatible.
42+
///
43+
/// ### Example
44+
/// ```rust
45+
/// use std::vec::Vec;
46+
/// ```
47+
/// Use instead:
48+
/// ```rust
49+
/// # extern crate alloc;
50+
/// use alloc::vec::Vec;
51+
/// ```
52+
#[clippy::version = "1.64.0"]
53+
pub STD_INSTEAD_OF_ALLOC,
54+
restriction,
55+
"type is imported from std when available in alloc"
56+
}
57+
58+
declare_clippy_lint! {
59+
/// ### What it does
60+
///
61+
/// Finds items imported through `alloc` when available through `core`.
62+
///
63+
/// ### Why is this bad?
64+
///
65+
/// Crates which have `no_std` compatibility and may optionally require alloc may wish to ensure types are
66+
/// imported from alloc to ensure disabling `alloc` does not cause the crate to fail to compile. This lint
67+
/// is also useful for crates migrating to become `no_std` compatible.
68+
///
69+
/// ### Example
70+
/// ```rust
71+
/// # extern crate alloc;
72+
/// use alloc::slice::from_ref;
73+
/// ```
74+
/// Use instead:
75+
/// ```rust
76+
/// use core::slice::from_ref;
77+
/// ```
78+
#[clippy::version = "1.64.0"]
79+
pub ALLOC_INSTEAD_OF_CORE,
80+
restriction,
81+
"type is imported from alloc when available in core"
82+
}
83+
84+
declare_lint_pass!(StdReexports => [STD_INSTEAD_OF_CORE, STD_INSTEAD_OF_ALLOC, ALLOC_INSTEAD_OF_CORE]);
85+
86+
impl<'tcx> LateLintPass<'tcx> for StdReexports {
87+
fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) {
88+
// std_instead_of_core
89+
check_path(cx, path, sym::std, sym::core, STD_INSTEAD_OF_CORE);
90+
// std_instead_of_alloc
91+
check_path(cx, path, sym::std, sym::alloc, STD_INSTEAD_OF_ALLOC);
92+
// alloc_instead_of_core
93+
check_path(cx, path, sym::alloc, sym::core, ALLOC_INSTEAD_OF_CORE);
94+
}
95+
}
96+
97+
fn check_path(cx: &LateContext<'_>, path: &Path<'_>, krate: Symbol, suggested_crate: Symbol, lint: &'static Lint) {
98+
if_chain! {
99+
// check if path resolves to the suggested crate.
100+
if let Res::Def(_, def_id) = path.res;
101+
if suggested_crate == cx.tcx.crate_name(def_id.krate);
102+
103+
// check if the first segment of the path is the crate we want to identify
104+
if let Some(path_root_segment) = get_first_segment(path);
105+
106+
// check if the path matches the crate we want to suggest the other path for.
107+
if krate == path_root_segment.ident.name;
108+
then {
109+
span_lint_and_help(
110+
cx,
111+
lint,
112+
path.span,
113+
&format!("used import from `{}` instead of `{}`", krate, suggested_crate),
114+
None,
115+
&format!("consider importing the item from `{}`", suggested_crate),
116+
);
117+
}
118+
}
119+
}
120+
121+
/// Returns the first named segment of a [`Path`].
122+
///
123+
/// If this is a global path (such as `::std::fmt::Debug`), then the segment after [`kw::PathRoot`]
124+
/// is returned.
125+
fn get_first_segment<'tcx>(path: &Path<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
126+
let segment = path.segments.first()?;
127+
128+
// A global path will have PathRoot as the first segment. In this case, return the segment after.
129+
if segment.ident.name == kw::PathRoot {
130+
path.segments.get(1)
131+
} else {
132+
Some(segment)
133+
}
134+
}

tests/ui/std_instead_of_core.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#![warn(clippy::std_instead_of_core)]
2+
#![allow(unused_imports)]
3+
4+
extern crate alloc;
5+
6+
#[warn(clippy::std_instead_of_core)]
7+
fn std_instead_of_core() {
8+
// Regular import
9+
use std::hash::Hasher;
10+
// Absolute path
11+
use ::std::hash::Hash;
12+
13+
// Multiple imports
14+
use std::fmt::{Debug, Result};
15+
16+
// Function calls
17+
let ptr = std::ptr::null::<u32>();
18+
let ptr_mut = ::std::ptr::null_mut::<usize>();
19+
20+
// Types
21+
let cell = std::cell::Cell::new(8u32);
22+
let cell_absolute = ::std::cell::Cell::new(8u32);
23+
}
24+
25+
#[warn(clippy::std_instead_of_alloc)]
26+
fn std_instead_of_alloc() {
27+
use std::vec::Vec;
28+
}
29+
30+
#[warn(clippy::alloc_instead_of_core)]
31+
fn alloc_instead_of_core() {
32+
use alloc::slice::from_ref;
33+
}
34+
35+
fn main() {
36+
std_instead_of_core();
37+
std_instead_of_alloc();
38+
alloc_instead_of_core();
39+
}

tests/ui/std_instead_of_core.stderr

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
error: used import from `std` instead of `core`
2+
--> $DIR/std_instead_of_core.rs:9:9
3+
|
4+
LL | use std::hash::Hasher;
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::std-instead-of-core` implied by `-D warnings`
8+
= help: consider importing the item from `core`
9+
10+
error: used import from `std` instead of `core`
11+
--> $DIR/std_instead_of_core.rs:11:9
12+
|
13+
LL | use ::std::hash::Hash;
14+
| ^^^^^^^^^^^^^^^^^
15+
|
16+
= help: consider importing the item from `core`
17+
18+
error: used import from `std` instead of `core`
19+
--> $DIR/std_instead_of_core.rs:14:20
20+
|
21+
LL | use std::fmt::{Debug, Result};
22+
| ^^^^^
23+
|
24+
= help: consider importing the item from `core`
25+
26+
error: used import from `std` instead of `core`
27+
--> $DIR/std_instead_of_core.rs:14:27
28+
|
29+
LL | use std::fmt::{Debug, Result};
30+
| ^^^^^^
31+
|
32+
= help: consider importing the item from `core`
33+
34+
error: used import from `std` instead of `core`
35+
--> $DIR/std_instead_of_core.rs:17:15
36+
|
37+
LL | let ptr = std::ptr::null::<u32>();
38+
| ^^^^^^^^^^^^^^^^^^^^^
39+
|
40+
= help: consider importing the item from `core`
41+
42+
error: used import from `std` instead of `core`
43+
--> $DIR/std_instead_of_core.rs:18:19
44+
|
45+
LL | let ptr_mut = ::std::ptr::null_mut::<usize>();
46+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47+
|
48+
= help: consider importing the item from `core`
49+
50+
error: used import from `std` instead of `core`
51+
--> $DIR/std_instead_of_core.rs:21:16
52+
|
53+
LL | let cell = std::cell::Cell::new(8u32);
54+
| ^^^^^^^^^^^^^^^
55+
|
56+
= help: consider importing the item from `core`
57+
58+
error: used import from `std` instead of `core`
59+
--> $DIR/std_instead_of_core.rs:22:25
60+
|
61+
LL | let cell_absolute = ::std::cell::Cell::new(8u32);
62+
| ^^^^^^^^^^^^^^^^^
63+
|
64+
= help: consider importing the item from `core`
65+
66+
error: used import from `std` instead of `alloc`
67+
--> $DIR/std_instead_of_core.rs:27:9
68+
|
69+
LL | use std::vec::Vec;
70+
| ^^^^^^^^^^^^^
71+
|
72+
= note: `-D clippy::std-instead-of-alloc` implied by `-D warnings`
73+
= help: consider importing the item from `alloc`
74+
75+
error: used import from `alloc` instead of `core`
76+
--> $DIR/std_instead_of_core.rs:32:9
77+
|
78+
LL | use alloc::slice::from_ref;
79+
| ^^^^^^^^^^^^^^^^^^^^^^
80+
|
81+
= note: `-D clippy::alloc-instead-of-core` implied by `-D warnings`
82+
= help: consider importing the item from `core`
83+
84+
error: aborting due to 10 previous errors
85+

0 commit comments

Comments
 (0)