Skip to content

Commit c1028af

Browse files
committed
Handle paths with leading :: (root)
Remove the tons of `allow`s
1 parent 8d17a94 commit c1028af

File tree

65 files changed

+468
-479
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+468
-479
lines changed

CHANGELOG.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4680,7 +4680,7 @@ Released 2018-09-13
46804680

46814681
<!-- lint disable no-unused-definitions -->
46824682
<!-- begin autogenerated links to lint list -->
4683-
[`absolute_symbol_paths`]: https://rust-lang.github.io/rust-clippy/master/index.html#absolute_symbol_paths
4683+
[`absolute_paths`]: https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths
46844684
[`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons
46854685
[`alloc_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#alloc_instead_of_core
46864686
[`allow_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes
@@ -5465,6 +5465,7 @@ Released 2018-09-13
54655465
[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement
54665466
[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes
54675467
[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings
5468-
[`absolute-symbol-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-symbol-paths-max-segments
5469-
[`absolute-symbol-paths-allow-std`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-symbol-paths-allow-std
5468+
[`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments
5469+
[`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates
54705470
<!-- end autogenerated links to configuration documentation -->
5471+
iguration documentation -->

book/src/lint_configuration.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -730,20 +730,21 @@ Whether to allow `r#""#` when `r""` can be used
730730
* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes)
731731

732732

733-
## `absolute-symbol-paths-max-segments`
734-
The maximum number of segments a path can have before being linted
733+
## `absolute-paths-max-segments`
734+
The maximum number of segments a path can have before being linted, anything above this will
735+
be linted.
735736

736-
**Default Value:** `3` (`u64`)
737+
**Default Value:** `2` (`u64`)
737738

738739
---
739740
**Affected lints:**
740741
* [`absolute_symbol_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_symbol_paths)
741742

742743

743-
## `absolute-symbol-paths-allow-std`
744-
Whether to allow paths originating from `core`/`std`/`alloc`
744+
## `absolute-paths-allowed-crates`
745+
Which crates to allow absolute paths from
745746

746-
**Default Value:** `false` (`bool`)
747+
**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`)
747748

748749
---
749750
**Affected lints:**

clippy_lints/src/absolute_paths.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
use clippy_utils::diagnostics::span_lint;
2+
use clippy_utils::source::snippet_opt;
3+
use rustc_data_structures::fx::FxHashSet;
4+
use rustc_hir::def::{DefKind, Res};
5+
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
6+
use rustc_hir::{HirId, ItemKind, Node, Path};
7+
use rustc_lint::{LateContext, LateLintPass};
8+
use rustc_session::{declare_tool_lint, impl_lint_pass};
9+
use rustc_span::symbol::kw;
10+
11+
declare_clippy_lint! {
12+
/// ### What it does
13+
/// Checks for usage of items through absolute paths, like `std::env::current_dir`.
14+
///
15+
/// ### Why is this bad?
16+
/// Many codebases have their own style when it comes to importing, but one that is seldom used
17+
/// is using absolute paths *everywhere*. This is generally considered unidiomatic, and you
18+
/// should add a `use` statement.
19+
///
20+
/// The default maximum segments (2) is pretty strict, you may want to increase this in
21+
/// `clippy.toml`.
22+
///
23+
/// Note: One exception to this is code from macro expansion - this does not lint such cases, as
24+
/// using absolute paths is the proper way of referencing items in one.
25+
///
26+
/// ### Example
27+
/// ```rust
28+
/// let x = std::f64::consts::PI;
29+
/// ```
30+
/// Use any of the below instead, or anything else:
31+
/// ```rust
32+
/// use std::f64;
33+
/// use std::f64::consts;
34+
/// use std::f64::consts::PI;
35+
/// let x = f64::consts::PI;
36+
/// let x = consts::PI;
37+
/// let x = PI;
38+
/// use std::f64::consts as f64_consts;
39+
/// let x = f64_consts::PI;
40+
/// ```
41+
#[clippy::version = "1.73.0"]
42+
pub ABSOLUTE_PATHS,
43+
restriction,
44+
"checks for usage of an item without a `use` statement"
45+
}
46+
impl_lint_pass!(AbsolutePaths => [ABSOLUTE_PATHS]);
47+
48+
pub struct AbsolutePaths {
49+
pub absolute_paths_max_segments: u64,
50+
pub absolute_paths_allowed_crates: FxHashSet<String>,
51+
}
52+
53+
impl LateLintPass<'_> for AbsolutePaths {
54+
// We should only lint `QPath::Resolved`s, but since `Path` is only used in `Resolved` and `UsePath`
55+
// we don't need to use a visitor or anything as we can just check if the `Node` for `hir_id` isn't
56+
// a `Use`
57+
#[expect(clippy::cast_possible_truncation)]
58+
fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) {
59+
let Self {
60+
absolute_paths_max_segments,
61+
absolute_paths_allowed_crates,
62+
} = self;
63+
64+
if !path.span.from_expansion()
65+
&& let Some(node) = cx.tcx.hir().find(hir_id)
66+
&& !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(_, _)))
67+
&& let [first, rest @ ..] = path.segments
68+
// Handle `::std`
69+
&& let (segment, len) = if first.ident.name == kw::PathRoot {
70+
// Indexing is fine as `PathRoot` must be followed by another segment. `len() - 1`
71+
// is fine here for the same reason
72+
(&rest[0], path.segments.len() - 1)
73+
} else {
74+
(first, path.segments.len())
75+
}
76+
&& len > *absolute_paths_max_segments as usize
77+
&& let Some(segment_snippet) = snippet_opt(cx, segment.ident.span)
78+
&& segment_snippet == segment.ident.as_str()
79+
{
80+
let is_abs_external =
81+
matches!(segment.res, Res::Def(DefKind::Mod, DefId { index, .. }) if index == CRATE_DEF_INDEX);
82+
let is_abs_crate = segment.ident.name == kw::Crate;
83+
84+
if is_abs_external && absolute_paths_allowed_crates.contains(segment.ident.name.as_str())
85+
|| is_abs_crate && absolute_paths_allowed_crates.contains("crate")
86+
{
87+
return;
88+
}
89+
90+
if is_abs_external || is_abs_crate {
91+
span_lint(
92+
cx,
93+
ABSOLUTE_PATHS,
94+
path.span,
95+
"consider bringing this path into scope with the `use` keyword",
96+
);
97+
}
98+
}
99+
}
100+
}

clippy_lints/src/absolute_symbol_paths.rs

Lines changed: 0 additions & 89 deletions
This file was deleted.

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
3737
crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
3838
#[cfg(feature = "internal")]
3939
crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
40-
crate::absolute_symbol_paths::ABSOLUTE_SYMBOL_PATHS_INFO,
40+
crate::absolute_paths::ABSOLUTE_PATHS_INFO,
4141
crate::allow_attributes::ALLOW_ATTRIBUTES_INFO,
4242
crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
4343
crate::approx_const::APPROX_CONSTANT_INFO,

clippy_lints/src/lib.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@
1010
#![feature(stmt_expr_attributes)]
1111
#![recursion_limit = "512"]
1212
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
13-
#![allow(
14-
clippy::absolute_symbol_paths,
15-
clippy::missing_docs_in_private_items,
16-
clippy::must_use_candidate
17-
)]
13+
#![allow(clippy::missing_docs_in_private_items, clippy::must_use_candidate)]
1814
#![warn(trivial_casts, trivial_numeric_casts)]
1915
// warn on lints, that are included in `rust-lang/rust`s bootstrap
2016
#![warn(rust_2018_idioms, unused_lifetimes)]
@@ -69,7 +65,7 @@ mod declared_lints;
6965
mod renamed_lints;
7066

7167
// begin lints modules, do not remove this comment, it’s used in `update_lints`
72-
mod absolute_symbol_paths;
68+
mod absolute_paths;
7369
mod allow_attributes;
7470
mod almost_complete_range;
7571
mod approx_const;
@@ -1085,12 +1081,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10851081
store.register_late_pass(move |_| Box::new(tuple_array_conversions::TupleArrayConversions { msrv: msrv() }));
10861082
store.register_late_pass(|_| Box::new(manual_float_methods::ManualFloatMethods));
10871083
store.register_late_pass(|_| Box::new(four_forward_slashes::FourForwardSlashes));
1088-
let absolute_symbol_paths_max_segments = conf.absolute_symbol_paths_max_segments;
1089-
let absolute_symbol_paths_allowed_crates = conf.absolute_symbol_paths_allowed_crates.clone();
1084+
let absolute_paths_max_segments = conf.absolute_paths_max_segments;
1085+
let absolute_paths_allowed_crates = conf.absolute_paths_allowed_crates.clone();
10901086
store.register_late_pass(move |_| {
1091-
Box::new(absolute_symbol_paths::AbsoluteSymbolPaths {
1092-
absolute_symbol_paths_max_segments,
1093-
absolute_symbol_paths_allowed_crates: absolute_symbol_paths_allowed_crates.clone(),
1087+
Box::new(absolute_paths::AbsolutePaths {
1088+
absolute_paths_max_segments,
1089+
absolute_paths_allowed_crates: absolute_paths_allowed_crates.clone(),
10941090
})
10951091
});
10961092
// add lints here, do not remove this comment, it's used in `new_lint`

clippy_lints/src/utils/conf.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -553,12 +553,13 @@ define_Conf! {
553553
(allow_one_hash_in_raw_strings: bool = false),
554554
/// Lint: ABSOLUTE_SYMBOL_PATHS.
555555
///
556-
/// The maximum number of segments a path can have before being linted
557-
(absolute_symbol_paths_max_segments: u64 = 3),
556+
/// The maximum number of segments a path can have before being linted, anything above this will
557+
/// be linted.
558+
(absolute_paths_max_segments: u64 = 2),
558559
/// Lint: ABSOLUTE_SYMBOL_PATHS.
559560
///
560-
/// Which crates to allow absolute symbols, `crate` will allow the local crate
561-
(absolute_symbol_paths_allowed_crates: rustc_data_structures::fx::FxHashSet<String> =
561+
/// Which crates to allow absolute paths from
562+
(absolute_paths_allowed_crates: rustc_data_structures::fx::FxHashSet<String> =
562563
rustc_data_structures::fx::FxHashSet::default()),
563564
}
564565

clippy_utils/src/check_proc_macro.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ pub trait WithSearchPat<'cx> {
354354
fn span(&self) -> Span;
355355
}
356356
macro_rules! impl_with_search_pat {
357-
($cx:ident: $ty:ident with $fn:ident $(($tcx:ident))? && $span_method:ident$($par:tt)?) => {
357+
($cx:ident: $ty:ident with $fn:ident $(($tcx:ident))?) => {
358358
impl<'cx> WithSearchPat<'cx> for $ty<'cx> {
359359
type Context = $cx<'cx>;
360360
#[allow(unused_variables)]
@@ -363,19 +363,18 @@ macro_rules! impl_with_search_pat {
363363
$fn($($tcx,)? self)
364364
}
365365
fn span(&self) -> Span {
366-
self.$span_method$($par)?
366+
self.span
367367
}
368368
}
369369
};
370370
}
371-
impl_with_search_pat!(LateContext: Expr with expr_search_pat(tcx) && span);
372-
impl_with_search_pat!(LateContext: Item with item_search_pat && span);
373-
impl_with_search_pat!(LateContext: TraitItem with trait_item_search_pat && span);
374-
impl_with_search_pat!(LateContext: ImplItem with impl_item_search_pat && span);
375-
impl_with_search_pat!(LateContext: FieldDef with field_def_search_pat && span);
376-
impl_with_search_pat!(LateContext: Variant with variant_search_pat && span);
377-
impl_with_search_pat!(LateContext: Ty with ty_search_pat && span);
378-
impl_with_search_pat!(LateContext: QPath with qpath_search_pat && span());
371+
impl_with_search_pat!(LateContext: Expr with expr_search_pat(tcx));
372+
impl_with_search_pat!(LateContext: Item with item_search_pat);
373+
impl_with_search_pat!(LateContext: TraitItem with trait_item_search_pat);
374+
impl_with_search_pat!(LateContext: ImplItem with impl_item_search_pat);
375+
impl_with_search_pat!(LateContext: FieldDef with field_def_search_pat);
376+
impl_with_search_pat!(LateContext: Variant with variant_search_pat);
377+
impl_with_search_pat!(LateContext: Ty with ty_search_pat);
379378

380379
impl<'cx> WithSearchPat<'cx> for (&FnKind<'cx>, &Body<'cx>, HirId, Span) {
381380
type Context = LateContext<'cx>;

tests/ui-cargo/module_style/fail_mod/src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![allow(clippy::absolute_symbol_paths)]
21
#![warn(clippy::self_named_module_files)]
32

43
mod bad;

tests/ui-internal/interning_defined_symbol.fixed

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
//@run-rustfix
22
#![deny(clippy::internal)]
3-
#![allow(
4-
clippy::absolute_symbol_paths,
5-
clippy::missing_clippy_version_attribute,
6-
clippy::let_unit_value
7-
)]
3+
#![allow(clippy::missing_clippy_version_attribute, clippy::let_unit_value)]
84
#![feature(rustc_private)]
95

106
extern crate rustc_span;

tests/ui-internal/interning_defined_symbol.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
//@run-rustfix
22
#![deny(clippy::internal)]
3-
#![allow(
4-
clippy::absolute_symbol_paths,
5-
clippy::missing_clippy_version_attribute,
6-
clippy::let_unit_value
7-
)]
3+
#![allow(clippy::missing_clippy_version_attribute, clippy::let_unit_value)]
84
#![feature(rustc_private)]
95

106
extern crate rustc_span;

0 commit comments

Comments
 (0)