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`]
This commit is contained in:
commit
c9f0d1aca7
7 changed files with 269 additions and 0 deletions
|
@ -3432,6 +3432,7 @@ Released 2018-09-13
|
||||||
<!-- lint disable no-unused-definitions -->
|
<!-- lint disable no-unused-definitions -->
|
||||||
<!-- begin autogenerated links to lint list -->
|
<!-- begin autogenerated links to lint list -->
|
||||||
[`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons
|
[`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons
|
||||||
|
[`alloc_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#alloc_instead_of_core
|
||||||
[`allow_attributes_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason
|
[`allow_attributes_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason
|
||||||
[`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range
|
[`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range
|
||||||
[`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
|
[`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
|
||||||
|
@ -3901,6 +3902,8 @@ Released 2018-09-13
|
||||||
[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
|
[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
|
||||||
[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
|
[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
|
||||||
[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
|
[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
|
||||||
|
[`std_instead_of_alloc`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_alloc
|
||||||
|
[`std_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_core
|
||||||
[`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string
|
[`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string
|
||||||
[`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add
|
[`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add
|
||||||
[`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign
|
[`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign
|
||||||
|
|
|
@ -497,6 +497,9 @@ store.register_lints(&[
|
||||||
size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
|
size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
|
||||||
slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
|
slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
|
||||||
stable_sort_primitive::STABLE_SORT_PRIMITIVE,
|
stable_sort_primitive::STABLE_SORT_PRIMITIVE,
|
||||||
|
std_instead_of_core::ALLOC_INSTEAD_OF_CORE,
|
||||||
|
std_instead_of_core::STD_INSTEAD_OF_ALLOC,
|
||||||
|
std_instead_of_core::STD_INSTEAD_OF_CORE,
|
||||||
strings::STRING_ADD,
|
strings::STRING_ADD,
|
||||||
strings::STRING_ADD_ASSIGN,
|
strings::STRING_ADD_ASSIGN,
|
||||||
strings::STRING_FROM_UTF8_AS_BYTES,
|
strings::STRING_FROM_UTF8_AS_BYTES,
|
||||||
|
|
|
@ -66,6 +66,9 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
|
||||||
LintId::of(shadow::SHADOW_SAME),
|
LintId::of(shadow::SHADOW_SAME),
|
||||||
LintId::of(shadow::SHADOW_UNRELATED),
|
LintId::of(shadow::SHADOW_UNRELATED),
|
||||||
LintId::of(single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES),
|
LintId::of(single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES),
|
||||||
|
LintId::of(std_instead_of_core::ALLOC_INSTEAD_OF_CORE),
|
||||||
|
LintId::of(std_instead_of_core::STD_INSTEAD_OF_ALLOC),
|
||||||
|
LintId::of(std_instead_of_core::STD_INSTEAD_OF_CORE),
|
||||||
LintId::of(strings::STRING_ADD),
|
LintId::of(strings::STRING_ADD),
|
||||||
LintId::of(strings::STRING_SLICE),
|
LintId::of(strings::STRING_SLICE),
|
||||||
LintId::of(strings::STRING_TO_STRING),
|
LintId::of(strings::STRING_TO_STRING),
|
||||||
|
|
|
@ -365,6 +365,7 @@ mod single_component_path_imports;
|
||||||
mod size_of_in_element_count;
|
mod size_of_in_element_count;
|
||||||
mod slow_vector_initialization;
|
mod slow_vector_initialization;
|
||||||
mod stable_sort_primitive;
|
mod stable_sort_primitive;
|
||||||
|
mod std_instead_of_core;
|
||||||
mod strings;
|
mod strings;
|
||||||
mod strlen_on_c_strings;
|
mod strlen_on_c_strings;
|
||||||
mod suspicious_operation_groupings;
|
mod suspicious_operation_groupings;
|
||||||
|
@ -915,6 +916,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||||
let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
|
let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
|
||||||
store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
|
store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
|
||||||
store.register_late_pass(|| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
|
store.register_late_pass(|| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
|
||||||
|
store.register_late_pass(|| Box::new(std_instead_of_core::StdReexports));
|
||||||
// add lints here, do not remove this comment, it's used in `new_lint`
|
// add lints here, do not remove this comment, it's used in `new_lint`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
134
clippy_lints/src/std_instead_of_core.rs
Normal file
134
clippy_lints/src/std_instead_of_core.rs
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
use clippy_utils::diagnostics::span_lint_and_help;
|
||||||
|
use rustc_hir::{def::Res, HirId, Path, PathSegment};
|
||||||
|
use rustc_lint::{LateContext, LateLintPass, Lint};
|
||||||
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
use rustc_span::{sym, symbol::kw, Symbol};
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
///
|
||||||
|
/// Finds items imported through `std` when available through `core`.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
///
|
||||||
|
/// Crates which have `no_std` compatibility may wish to ensure types are imported from core to ensure
|
||||||
|
/// disabling `std` does not cause the crate to fail to compile. This lint is also useful for crates
|
||||||
|
/// migrating to become `no_std` compatible.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```rust
|
||||||
|
/// use std::hash::Hasher;
|
||||||
|
/// ```
|
||||||
|
/// Use instead:
|
||||||
|
/// ```rust
|
||||||
|
/// use core::hash::Hasher;
|
||||||
|
/// ```
|
||||||
|
#[clippy::version = "1.64.0"]
|
||||||
|
pub STD_INSTEAD_OF_CORE,
|
||||||
|
restriction,
|
||||||
|
"type is imported from std when available in core"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
///
|
||||||
|
/// Finds items imported through `std` when available through `alloc`.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
///
|
||||||
|
/// Crates which have `no_std` compatibility and require alloc may wish to ensure types are imported from
|
||||||
|
/// alloc to ensure disabling `std` does not cause the crate to fail to compile. This lint is also useful
|
||||||
|
/// for crates migrating to become `no_std` compatible.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```rust
|
||||||
|
/// use std::vec::Vec;
|
||||||
|
/// ```
|
||||||
|
/// Use instead:
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate alloc;
|
||||||
|
/// use alloc::vec::Vec;
|
||||||
|
/// ```
|
||||||
|
#[clippy::version = "1.64.0"]
|
||||||
|
pub STD_INSTEAD_OF_ALLOC,
|
||||||
|
restriction,
|
||||||
|
"type is imported from std when available in alloc"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
///
|
||||||
|
/// Finds items imported through `alloc` when available through `core`.
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
///
|
||||||
|
/// Crates which have `no_std` compatibility and may optionally require alloc may wish to ensure types are
|
||||||
|
/// imported from alloc to ensure disabling `alloc` does not cause the crate to fail to compile. This lint
|
||||||
|
/// is also useful for crates migrating to become `no_std` compatible.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate alloc;
|
||||||
|
/// use alloc::slice::from_ref;
|
||||||
|
/// ```
|
||||||
|
/// Use instead:
|
||||||
|
/// ```rust
|
||||||
|
/// use core::slice::from_ref;
|
||||||
|
/// ```
|
||||||
|
#[clippy::version = "1.64.0"]
|
||||||
|
pub ALLOC_INSTEAD_OF_CORE,
|
||||||
|
restriction,
|
||||||
|
"type is imported from alloc when available in core"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_lint_pass!(StdReexports => [STD_INSTEAD_OF_CORE, STD_INSTEAD_OF_ALLOC, ALLOC_INSTEAD_OF_CORE]);
|
||||||
|
|
||||||
|
impl<'tcx> LateLintPass<'tcx> for StdReexports {
|
||||||
|
fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) {
|
||||||
|
// std_instead_of_core
|
||||||
|
check_path(cx, path, sym::std, sym::core, STD_INSTEAD_OF_CORE);
|
||||||
|
// std_instead_of_alloc
|
||||||
|
check_path(cx, path, sym::std, sym::alloc, STD_INSTEAD_OF_ALLOC);
|
||||||
|
// alloc_instead_of_core
|
||||||
|
check_path(cx, path, sym::alloc, sym::core, ALLOC_INSTEAD_OF_CORE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_path(cx: &LateContext<'_>, path: &Path<'_>, krate: Symbol, suggested_crate: Symbol, lint: &'static Lint) {
|
||||||
|
if_chain! {
|
||||||
|
// check if path resolves to the suggested crate.
|
||||||
|
if let Res::Def(_, def_id) = path.res;
|
||||||
|
if suggested_crate == cx.tcx.crate_name(def_id.krate);
|
||||||
|
|
||||||
|
// check if the first segment of the path is the crate we want to identify
|
||||||
|
if let Some(path_root_segment) = get_first_segment(path);
|
||||||
|
|
||||||
|
// check if the path matches the crate we want to suggest the other path for.
|
||||||
|
if krate == path_root_segment.ident.name;
|
||||||
|
then {
|
||||||
|
span_lint_and_help(
|
||||||
|
cx,
|
||||||
|
lint,
|
||||||
|
path.span,
|
||||||
|
&format!("used import from `{}` instead of `{}`", krate, suggested_crate),
|
||||||
|
None,
|
||||||
|
&format!("consider importing the item from `{}`", suggested_crate),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the first named segment of a [`Path`].
|
||||||
|
///
|
||||||
|
/// If this is a global path (such as `::std::fmt::Debug`), then the segment after [`kw::PathRoot`]
|
||||||
|
/// is returned.
|
||||||
|
fn get_first_segment<'tcx>(path: &Path<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
|
||||||
|
let segment = path.segments.first()?;
|
||||||
|
|
||||||
|
// A global path will have PathRoot as the first segment. In this case, return the segment after.
|
||||||
|
if segment.ident.name == kw::PathRoot {
|
||||||
|
path.segments.get(1)
|
||||||
|
} else {
|
||||||
|
Some(segment)
|
||||||
|
}
|
||||||
|
}
|
39
tests/ui/std_instead_of_core.rs
Normal file
39
tests/ui/std_instead_of_core.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#![warn(clippy::std_instead_of_core)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
#[warn(clippy::std_instead_of_core)]
|
||||||
|
fn std_instead_of_core() {
|
||||||
|
// Regular import
|
||||||
|
use std::hash::Hasher;
|
||||||
|
// Absolute path
|
||||||
|
use ::std::hash::Hash;
|
||||||
|
|
||||||
|
// Multiple imports
|
||||||
|
use std::fmt::{Debug, Result};
|
||||||
|
|
||||||
|
// Function calls
|
||||||
|
let ptr = std::ptr::null::<u32>();
|
||||||
|
let ptr_mut = ::std::ptr::null_mut::<usize>();
|
||||||
|
|
||||||
|
// Types
|
||||||
|
let cell = std::cell::Cell::new(8u32);
|
||||||
|
let cell_absolute = ::std::cell::Cell::new(8u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[warn(clippy::std_instead_of_alloc)]
|
||||||
|
fn std_instead_of_alloc() {
|
||||||
|
use std::vec::Vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[warn(clippy::alloc_instead_of_core)]
|
||||||
|
fn alloc_instead_of_core() {
|
||||||
|
use alloc::slice::from_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
std_instead_of_core();
|
||||||
|
std_instead_of_alloc();
|
||||||
|
alloc_instead_of_core();
|
||||||
|
}
|
85
tests/ui/std_instead_of_core.stderr
Normal file
85
tests/ui/std_instead_of_core.stderr
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
error: used import from `std` instead of `core`
|
||||||
|
--> $DIR/std_instead_of_core.rs:9:9
|
||||||
|
|
|
||||||
|
LL | use std::hash::Hasher;
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `-D clippy::std-instead-of-core` implied by `-D warnings`
|
||||||
|
= help: consider importing the item from `core`
|
||||||
|
|
||||||
|
error: used import from `std` instead of `core`
|
||||||
|
--> $DIR/std_instead_of_core.rs:11:9
|
||||||
|
|
|
||||||
|
LL | use ::std::hash::Hash;
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider importing the item from `core`
|
||||||
|
|
||||||
|
error: used import from `std` instead of `core`
|
||||||
|
--> $DIR/std_instead_of_core.rs:14:20
|
||||||
|
|
|
||||||
|
LL | use std::fmt::{Debug, Result};
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
= help: consider importing the item from `core`
|
||||||
|
|
||||||
|
error: used import from `std` instead of `core`
|
||||||
|
--> $DIR/std_instead_of_core.rs:14:27
|
||||||
|
|
|
||||||
|
LL | use std::fmt::{Debug, Result};
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider importing the item from `core`
|
||||||
|
|
||||||
|
error: used import from `std` instead of `core`
|
||||||
|
--> $DIR/std_instead_of_core.rs:17:15
|
||||||
|
|
|
||||||
|
LL | let ptr = std::ptr::null::<u32>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider importing the item from `core`
|
||||||
|
|
||||||
|
error: used import from `std` instead of `core`
|
||||||
|
--> $DIR/std_instead_of_core.rs:18:19
|
||||||
|
|
|
||||||
|
LL | let ptr_mut = ::std::ptr::null_mut::<usize>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider importing the item from `core`
|
||||||
|
|
||||||
|
error: used import from `std` instead of `core`
|
||||||
|
--> $DIR/std_instead_of_core.rs:21:16
|
||||||
|
|
|
||||||
|
LL | let cell = std::cell::Cell::new(8u32);
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider importing the item from `core`
|
||||||
|
|
||||||
|
error: used import from `std` instead of `core`
|
||||||
|
--> $DIR/std_instead_of_core.rs:22:25
|
||||||
|
|
|
||||||
|
LL | let cell_absolute = ::std::cell::Cell::new(8u32);
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider importing the item from `core`
|
||||||
|
|
||||||
|
error: used import from `std` instead of `alloc`
|
||||||
|
--> $DIR/std_instead_of_core.rs:27:9
|
||||||
|
|
|
||||||
|
LL | use std::vec::Vec;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `-D clippy::std-instead-of-alloc` implied by `-D warnings`
|
||||||
|
= help: consider importing the item from `alloc`
|
||||||
|
|
||||||
|
error: used import from `alloc` instead of `core`
|
||||||
|
--> $DIR/std_instead_of_core.rs:32:9
|
||||||
|
|
|
||||||
|
LL | use alloc::slice::from_ref;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `-D clippy::alloc-instead-of-core` implied by `-D warnings`
|
||||||
|
= help: consider importing the item from `core`
|
||||||
|
|
||||||
|
error: aborting due to 10 previous errors
|
||||||
|
|
Loading…
Add table
Reference in a new issue