Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new lint: use_crate_prefix_for_self_imports #13662

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6115,6 +6115,7 @@ Released 2018-09-13
[`unwrap_or_else_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_or_else_default
[`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used
[`upper_case_acronyms`]: https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms
[`use_crate_prefix_for_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_crate_prefix_for_self_imports
[`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug
[`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self
[`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding
Expand Down
4 changes: 2 additions & 2 deletions clippy_config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ mod metadata;
pub mod msrvs;
pub mod types;

pub use conf::{Conf, get_configuration_metadata, lookup_conf_file, sanitize_explanation};
pub use metadata::ClippyConfiguration;
pub use crate::conf::{Conf, get_configuration_metadata, lookup_conf_file, sanitize_explanation};
pub use crate::metadata::ClippyConfiguration;
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::unwrap::UNNECESSARY_UNWRAP_INFO,
crate::unwrap_in_result::UNWRAP_IN_RESULT_INFO,
crate::upper_case_acronyms::UPPER_CASE_ACRONYMS_INFO,
crate::use_crate_prefix_for_self_imports::USE_CRATE_PREFIX_FOR_SELF_IMPORTS_INFO,
crate::use_self::USE_SELF_INFO,
crate::useless_conversion::USELESS_CONVERSION_INFO,
crate::vec::USELESS_VEC_INFO,
Expand Down
6 changes: 4 additions & 2 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ mod unused_unit;
mod unwrap;
mod unwrap_in_result;
mod upper_case_acronyms;
mod use_crate_prefix_for_self_imports;
mod use_self;
mod useless_conversion;
mod vec;
Expand All @@ -397,11 +398,11 @@ mod zero_sized_map_values;
mod zombie_processes;
// end lints modules, do not remove this comment, it’s used in `update_lints`

use crate::utils::attr_collector::{AttrCollector, AttrStorage};
use clippy_config::{Conf, get_configuration_metadata, sanitize_explanation};
use clippy_utils::macros::FormatArgsStorage;
use rustc_data_structures::fx::FxHashSet;
use rustc_lint::{Lint, LintId};
use utils::attr_collector::{AttrCollector, AttrStorage};

/// Register all pre expansion lints
///
Expand Down Expand Up @@ -468,7 +469,7 @@ pub(crate) enum LintCategory {
}

#[allow(clippy::enum_glob_use)]
use LintCategory::*;
use crate::LintCategory::*;

impl LintCategory {
fn is_all(self) -> bool {
Expand Down Expand Up @@ -963,5 +964,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(|_| Box::new(manual_ignore_case_cmp::ManualIgnoreCaseCmp));
store.register_late_pass(|_| Box::new(unnecessary_literal_bound::UnnecessaryLiteralBound));
store.register_late_pass(move |_| Box::new(arbitrary_source_item_ordering::ArbitrarySourceItemOrdering::new(conf)));
store.register_late_pass(|_| Box::new(use_crate_prefix_for_self_imports::UseCratePrefixForSelfImports));
// add lints here, do not remove this comment, it's used in `new_lint`
}
88 changes: 88 additions & 0 deletions clippy_lints/src/use_crate_prefix_for_self_imports.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use def_id::LOCAL_CRATE;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{Item, ItemKind, def_id};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::declare_lint_pass;
use rustc_span::{FileName, RealFileName};

declare_clippy_lint! {
/// ### What it does
/// This lint checks for imports from the current crate that do not use the `crate::` prefix.
/// It suggests using `crate::` to make it clear that the item is from the same crate.
///
/// ### Why is this bad?
/// When imports from the current crate lack the `crate::` prefix, it can make the code less readable
/// because it’s not immediately clear if the imported item is from the current crate or an external dependency.
/// Using `crate::` for self-imports provides a consistent style, making the origin of each import clear.
/// This helps reduce confusion and maintain a uniform codebase.
///
/// ### Example
/// ```rust,ignore
/// // lib.rs
/// mod foo;
/// use foo::bar;
/// ```
///
/// ```rust,ignore
/// // foo.rs
/// #[path = "./foo.rs"]
/// pub fn bar() {}
/// ```
///
/// Use instead:
/// ```rust,ignore
/// // lib.rs
/// mod foo;
/// use crate::foo::bar;
/// ```
///
/// ```rust,ignore
/// // foo.rs
/// #[path = "./foo.rs"]
/// pub fn bar() {}
/// ```
#[clippy::version = "1.84.0"]
pub USE_CRATE_PREFIX_FOR_SELF_IMPORTS,
style,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I understand that clearing up possible path confusion is a worthy cause, I'm afraid that introducing the lint as warn-by-default will lead to a lot of noise and broken CI jobs.

I'll discuss this on zulip.

"checks that imports from the current crate use the `crate::` prefix"
}

declare_lint_pass!(UseCratePrefixForSelfImports => [USE_CRATE_PREFIX_FOR_SELF_IMPORTS]);

impl LateLintPass<'_> for UseCratePrefixForSelfImports {
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
let FileName::Real(RealFileName::LocalPath(p)) = cx.sess().source_map().span_to_filename(item.span) else {
return;
};
let Some(file_name) = p.file_name() else {
return;
};
// only check `main.rs` and `lib.rs`
if !(file_name == "main.rs" || file_name == "lib.rs") {
return;
}

if let ItemKind::Use(use_path, _) = &item.kind {
if let Some(segment) = use_path.segments.first()
&& let Res::Def(_, def_id) = segment.res
&& def_id.krate == LOCAL_CRATE
{
let root = segment.ident.name;
if root != rustc_span::symbol::kw::Crate && root != rustc_span::symbol::kw::Super {
span_lint_and_sugg(
cx,
USE_CRATE_PREFIX_FOR_SELF_IMPORTS,
segment.ident.span,
"this import is not clear",
"prefix with `crate::`",
format!("crate::{}", snippet_opt(cx, segment.ident.span).unwrap()),
Applicability::MachineApplicable,
);
}
}
}
}
}
5 changes: 2 additions & 3 deletions clippy_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ use rustc_hir::{
};
use rustc_lexer::{TokenKind, tokenize};
use rustc_lint::{LateContext, Level, Lint, LintContext};
use rustc_middle::hir::nested_filter;
use rustc_middle::hir::place::PlaceBase;
use rustc_middle::mir::Const;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
Expand All @@ -124,13 +125,11 @@ use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{Ident, Symbol, kw};
use rustc_span::{InnerSpan, Span, sym};
use rustc_target::abi::Integer;
use visitors::Visitable;

use crate::consts::{ConstEvalCtxt, Constant, mir_to_const};
use crate::higher::Range;
use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type};
use crate::visitors::for_each_expr_without_closures;
use rustc_middle::hir::nested_filter;
use crate::visitors::{Visitable, for_each_expr_without_closures};

#[macro_export]
macro_rules! extract_msrv_attr {
Expand Down
10 changes: 10 additions & 0 deletions tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: this import is not clear
--> src/main.rs:1:5
|
1 | use foo::Foo;
| ^^^ help: prefix with `crate::`: `crate::foo`
|
= note: `-D clippy::use-crate-prefix-for-self-imports` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::use_crate_prefix_for_self_imports)]`

error: could not compile `fail` (bin "fail") due to 1 previous error
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "fail"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub struct Foo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use foo::Foo;

mod foo;

fn main() {
let _foo = Foo;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "pass"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub struct Foo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use crate::foo::Foo;

mod foo;

fn main() {
let _foo = Foo;
}
5 changes: 5 additions & 0 deletions tests/ui/use_crate_prefix_for_self_imports.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#![warn(clippy::use_crate_prefix_for_self_imports)]

fn main() {
// test code goes here
}