-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
std_instead_of_core, std_instead_of_alloc, alloc_instead_of_core
- Loading branch information
Showing
7 changed files
with
269 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|