Refactor absolute_paths:

* Check the path length first
* Use `is_from_proc_macro`
* Use symbols instead of strings when checking crate names
This commit is contained in:
Jason Newcomb 2024-07-04 19:00:17 -04:00
parent 1c81105b43
commit f9509d3574
16 changed files with 418 additions and 228 deletions

View File

@ -1,6 +1,6 @@
use clippy_config::Conf; use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint; use clippy_utils::diagnostics::span_lint;
use clippy_utils::source::snippet_opt; use clippy_utils::is_from_proc_macro;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
@ -8,6 +8,7 @@
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass; use rustc_session::impl_lint_pass;
use rustc_span::symbol::kw; use rustc_span::symbol::kw;
use rustc_span::Symbol;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -24,6 +25,13 @@
/// Note: One exception to this is code from macro expansion - this does not lint such cases, as /// Note: One exception to this is code from macro expansion - this does not lint such cases, as
/// using absolute paths is the proper way of referencing items in one. /// using absolute paths is the proper way of referencing items in one.
/// ///
/// ### Known issues
///
/// There are currently a few cases which are not caught by this lint:
/// * Macro calls. e.g. `path::to::macro!()`
/// * Derive macros. e.g. `#[derive(path::to::macro)]`
/// * Attribute macros. e.g. `#[path::to::macro]`
///
/// ### Example /// ### Example
/// ```no_run /// ```no_run
/// let x = std::f64::consts::PI; /// let x = std::f64::consts::PI;
@ -48,63 +56,66 @@
pub struct AbsolutePaths { pub struct AbsolutePaths {
pub absolute_paths_max_segments: u64, pub absolute_paths_max_segments: u64,
pub absolute_paths_allowed_crates: &'static FxHashSet<String>, pub absolute_paths_allowed_crates: FxHashSet<Symbol>,
} }
impl AbsolutePaths { impl AbsolutePaths {
pub fn new(conf: &'static Conf) -> Self { pub fn new(conf: &'static Conf) -> Self {
Self { Self {
absolute_paths_max_segments: conf.absolute_paths_max_segments, absolute_paths_max_segments: conf.absolute_paths_max_segments,
absolute_paths_allowed_crates: &conf.absolute_paths_allowed_crates, absolute_paths_allowed_crates: conf
.absolute_paths_allowed_crates
.iter()
.map(|x| Symbol::intern(x))
.collect(),
} }
} }
} }
impl LateLintPass<'_> for AbsolutePaths { impl<'tcx> LateLintPass<'tcx> for AbsolutePaths {
// We should only lint `QPath::Resolved`s, but since `Path` is only used in `Resolved` and `UsePath` // We should only lint `QPath::Resolved`s, but since `Path` is only used in `Resolved` and `UsePath`
// we don't need to use a visitor or anything as we can just check if the `Node` for `hir_id` isn't // we don't need to use a visitor or anything as we can just check if the `Node` for `hir_id` isn't
// a `Use` // a `Use`
#[expect(clippy::cast_possible_truncation)] fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, hir_id: HirId) {
fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) { let segments = match path.segments {
let Self { [] | [_] => return,
absolute_paths_max_segments, // Don't count enum variants and trait items as part of the length.
absolute_paths_allowed_crates, [rest @ .., _]
} = self; if let [.., s] = rest
&& matches!(s.res, Res::Def(DefKind::Enum | DefKind::Trait | DefKind::TraitAlias, _)) =>
if !path.span.from_expansion()
&& let node = cx.tcx.hir_node(hir_id)
&& !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(_, _)))
&& let [first, rest @ ..] = path.segments
// Handle `::std`
&& let (segment, len) = if first.ident.name == kw::PathRoot {
// Indexing is fine as `PathRoot` must be followed by another segment. `len() - 1`
// is fine here for the same reason
(&rest[0], path.segments.len() - 1)
} else {
(first, path.segments.len())
}
&& len > *absolute_paths_max_segments as usize
&& let Some(segment_snippet) = snippet_opt(cx, segment.ident.span)
&& segment_snippet == segment.ident.as_str()
{
let is_abs_external =
matches!(segment.res, Res::Def(DefKind::Mod, DefId { index, .. }) if index == CRATE_DEF_INDEX);
let is_abs_crate = segment.ident.name == kw::Crate;
if is_abs_external && absolute_paths_allowed_crates.contains(segment.ident.name.as_str())
|| is_abs_crate && absolute_paths_allowed_crates.contains("crate")
{ {
rest
},
path => path,
};
if let [s1, s2, ..] = segments
&& let has_root = s1.ident.name == kw::PathRoot
&& let first = if has_root { s2 } else { s1 }
&& let len = segments.len() - usize::from(has_root)
&& len as u64 > self.absolute_paths_max_segments
&& let crate_name = if let Res::Def(DefKind::Mod, DefId { index, .. }) = first.res
&& index == CRATE_DEF_INDEX
{
// `other_crate::foo` or `::other_crate::foo`
first.ident.name
} else if first.ident.name == kw::Crate || has_root {
// `::foo` or `crate::foo`
kw::Crate
} else {
return; return;
} }
&& !path.span.from_expansion()
if is_abs_external || is_abs_crate { && let node = cx.tcx.hir_node(hir_id)
span_lint( && !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(..)))
cx, && !self.absolute_paths_allowed_crates.contains(&crate_name)
ABSOLUTE_PATHS, && !is_from_proc_macro(cx, path)
path.span, {
"consider bringing this path into scope with the `use` keyword", span_lint(
); cx,
} ABSOLUTE_PATHS,
path.span,
"consider bringing this path into scope with the `use` keyword",
);
} }
} }
} }

View File

@ -123,16 +123,14 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) {
fn path_search_pat(path: &Path<'_>) -> (Pat, Pat) { fn path_search_pat(path: &Path<'_>) -> (Pat, Pat) {
let (head, tail) = match path.segments { let (head, tail) = match path.segments {
[head, .., tail] => (head, tail),
[p] => (p, p),
[] => return (Pat::Str(""), Pat::Str("")), [] => return (Pat::Str(""), Pat::Str("")),
[p] => (Pat::Sym(p.ident.name), p),
// QPath::Resolved can have a path that looks like `<Foo as Bar>::baz` where
// the path (`Bar::baz`) has it's span covering the whole QPath.
[.., tail] => (Pat::Str(""), tail),
}; };
( (
if head.ident.name == kw::PathRoot { head,
Pat::Str("::")
} else {
Pat::Sym(head.ident.name)
},
if tail.args.is_some() { if tail.args.is_some() {
Pat::Str(">") Pat::Str(">")
} else { } else {

View File

@ -1,29 +1,44 @@
error: consider bringing this path into scope with the `use` keyword error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:40:5 --> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13
| |
LL | std::f32::MAX; LL | let _ = std::path::is_separator(' ');
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: `-D clippy::absolute-paths` implied by `-D warnings` note: the lint level is defined here
= help: to override `-D warnings` add `#[allow(clippy::absolute_paths)]` --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9
|
LL | #![deny(clippy::absolute_paths)]
| ^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:41:5 --> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13
| |
LL | core::f32::MAX; LL | let _ = ::std::path::MAIN_SEPARATOR;
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:42:5 --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13
| |
LL | ::core::f32::MAX; LL | let _ = std::collections::hash_map::HashMap::<i32, i32>::new();
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:58:5 --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31
| |
LL | ::std::f32::MAX; LL | let _: &std::path::Path = std::path::Path::new("");
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13
|
LL | let _: &std::path::Path = std::path::Path::new("");
| ^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13
|
LL | let _ = std::option::Option::None::<i32>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors

View File

@ -0,0 +1,14 @@
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13
|
LL | let _ = std::collections::hash_map::HashMap::<i32, i32>::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9
|
LL | #![deny(clippy::absolute_paths)]
| ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -0,0 +1,80 @@
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13
|
LL | let _ = std::path::is_separator(' ');
| ^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9
|
LL | #![deny(clippy::absolute_paths)]
| ^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13
|
LL | let _ = ::std::path::MAIN_SEPARATOR;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13
|
LL | let _ = std::collections::hash_map::HashMap::<i32, i32>::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31
|
LL | let _: &std::path::Path = std::path::Path::new("");
| ^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13
|
LL | let _: &std::path::Path = std::path::Path::new("");
| ^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:37:13
|
LL | let _ = ::core::clone::Clone::clone(&0i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:40:13
|
LL | let _ = <i32 as core::clone::Clone>::clone(&0i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13
|
LL | let _ = std::option::Option::None::<i32>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:65:17
|
LL | impl<T: core::cmp::Eq> core::fmt::Display for X<T>
| ^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:70:18
|
LL | where T: core::clone::Clone
| ^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:65:32
|
LL | impl<T: core::cmp::Eq> core::fmt::Display for X<T>
| ^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:116:5
|
LL | crate::m1::S
| ^^^^^^^^^^^^
error: aborting due to 12 previous errors

View File

@ -1,71 +0,0 @@
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:40:5
|
LL | std::f32::MAX;
| ^^^^^^^^^^^^^
|
= note: `-D clippy::absolute-paths` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::absolute_paths)]`
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:41:5
|
LL | core::f32::MAX;
| ^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:42:5
|
LL | ::core::f32::MAX;
| ^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:43:5
|
LL | crate::a::b::c::C;
| ^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:44:5
|
LL | crate::a::b::c::d::e::f::F;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:45:5
|
LL | crate::a::A;
| ^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:46:5
|
LL | crate::a::b::B;
| ^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:47:5
|
LL | crate::a::b::c::C::ZERO;
| ^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:48:5
|
LL | helper::b::c::d::e::f();
| ^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:49:5
|
LL | ::helper::b::c::d::e::f();
| ^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:58:5
|
LL | ::std::f32::MAX;
| ^^^^^^^^^^^^^^^
error: aborting due to 11 previous errors

View File

@ -0,0 +1,98 @@
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13
|
LL | let _ = std::path::is_separator(' ');
| ^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9
|
LL | #![deny(clippy::absolute_paths)]
| ^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13
|
LL | let _ = ::std::path::MAIN_SEPARATOR;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13
|
LL | let _ = std::collections::hash_map::HashMap::<i32, i32>::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31
|
LL | let _: &std::path::Path = std::path::Path::new("");
| ^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13
|
LL | let _: &std::path::Path = std::path::Path::new("");
| ^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:37:13
|
LL | let _ = ::core::clone::Clone::clone(&0i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:40:13
|
LL | let _ = <i32 as core::clone::Clone>::clone(&0i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13
|
LL | let _ = std::option::Option::None::<i32>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:65:17
|
LL | impl<T: core::cmp::Eq> core::fmt::Display for X<T>
| ^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:70:18
|
LL | where T: core::clone::Clone
| ^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:65:32
|
LL | impl<T: core::cmp::Eq> core::fmt::Display for X<T>
| ^^^^^^^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:113:14
|
LL | pub const _: crate::S = {
| ^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:114:9
|
LL | let crate::S = m1::S;
| ^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:116:5
|
LL | crate::m1::S
| ^^^^^^^^^^^^
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths.rs:122:14
|
LL | let _ = <crate::S as Clone>::clone(&m1::S);
| ^^^^^^^^
error: aborting due to 15 previous errors

View File

@ -1,97 +1,123 @@
//@aux-build:../../ui/auxiliary/proc_macros.rs //@aux-build:../../ui/auxiliary/proc_macros.rs
//@aux-build:helper.rs //@revisions: default allow_crates allow_long no_short
//@revisions: allow_crates disallow_crates //@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/default
//@[allow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_crates //@[allow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_crates
//@[disallow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/disallow_crates //@[allow_long] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_long
#![allow(clippy::no_effect, clippy::legacy_numeric_constants, unused)] //@[no_short] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/no_short
#![warn(clippy::absolute_paths)] #![deny(clippy::absolute_paths)]
#![feature(decl_macro)]
extern crate helper;
#[macro_use]
extern crate proc_macros; extern crate proc_macros;
use proc_macros::{external, inline_macros, with_span};
pub mod a { #[inline_macros]
pub mod b { fn main() {
pub mod c { let _ = std::path::is_separator(' ');
pub struct C; //~[default]^ absolute_paths
//~[allow_crates]| absolute_paths
//~[no_short]| absolute_paths
impl C { // Make sure this is treated as having three path segments, not four.
pub const ZERO: u32 = 0; let _ = ::std::path::MAIN_SEPARATOR;
} //~[default]^ absolute_paths
//~[allow_crates]| absolute_paths
//~[no_short]| absolute_paths
pub mod d { let _ = std::collections::hash_map::HashMap::<i32, i32>::new(); //~ absolute_paths
pub mod e {
pub mod f { // Note `std::path::Path::new` is treated as having three parts
pub struct F; let _: &std::path::Path = std::path::Path::new("");
} //~[default]^ absolute_paths
} //~[default]| absolute_paths
//~[allow_crates]| absolute_paths
//~[allow_crates]| absolute_paths
//~[no_short]| absolute_paths
//~[no_short]| absolute_paths
// Treated as having three parts.
let _ = ::core::clone::Clone::clone(&0i32);
//~[default]^ absolute_paths
//~[no_short]| absolute_paths
let _ = <i32 as core::clone::Clone>::clone(&0i32);
//~[default]^ absolute_paths
//~[no_short]| absolute_paths
let _ = std::option::Option::None::<i32>;
//~[default]^ absolute_paths
//~[allow_crates]| absolute_paths
//~[no_short]| absolute_paths
{
// FIXME: macro calls should be checked.
let x = 1i32;
let _ = core::ptr::addr_of!(x);
}
{
// FIXME: derive macro paths should be checked.
#[derive(core::clone::Clone)]
struct S;
}
{
use core::fmt;
use core::marker::PhantomData;
struct X<T>(PhantomData<T>);
impl<T: core::cmp::Eq> core::fmt::Display for X<T>
//~[default]^ absolute_paths
//~[default]| absolute_paths
//~[no_short]| absolute_paths
//~[no_short]| absolute_paths
where T: core::clone::Clone
//~[no_short]^ absolute_paths
//~[default]| absolute_paths
{
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
Ok(())
} }
} }
pub struct B;
} }
pub struct A; {
} mod m1 {
pub(crate) mod m2 {
pub(crate) const FOO: i32 = 0;
}
}
let _ = m1::m2::FOO;
}
fn main() {
f32::max(1.0, 2.0);
std::f32::MAX;
core::f32::MAX;
::core::f32::MAX;
crate::a::b::c::C;
crate::a::b::c::d::e::f::F;
crate::a::A;
crate::a::b::B;
crate::a::b::c::C::ZERO;
helper::b::c::d::e::f();
::helper::b::c::d::e::f();
fn b() -> a::b::B {
todo!()
}
std::println!("a");
let x = 1;
std::ptr::addr_of!(x);
// Test we handle max segments with `PathRoot` properly; this has 4 segments but we should say it
// has 3
::std::f32::MAX;
// Do not lint due to the above
::helper::a();
// Do not lint
helper::a();
use crate::a::b::c::C;
use a::b;
use std::f32::MAX;
a::b::c::d::e::f::F;
b::c::C;
fn a() -> a::A {
todo!()
}
use a::b::c;
fn c() -> c::C {
todo!()
}
fn d() -> Result<(), ()> {
todo!()
}
external! {
crate::a::b::c::C::ZERO;
}
// For some reason, `path.span.from_expansion()` takes care of this for us
with_span! { with_span! {
span span
crate::a::b::c::C::ZERO; let _ = std::path::is_separator(' ');
} }
macro_rules! local_crate {
() => { external! {
crate::a::b::c::C::ZERO; let _ = std::path::is_separator(' ');
};
} }
macro local_crate_2_0() {
crate::a::b::c::C::ZERO; inline! {
let _ = std::path::is_separator(' ');
} }
local_crate!(); }
local_crate_2_0!();
pub use core::cmp::Ordering;
pub use std::fs::File;
#[derive(Clone)]
pub struct S;
mod m1 {
pub use crate::S;
}
//~[no_short]v absolute_paths
pub const _: crate::S = {
let crate::S = m1::S; //~[no_short] absolute_paths
crate::m1::S
//~[default]^ absolute_paths
//~[no_short]| absolute_paths
};
pub fn f() {
let _ = <crate::S as Clone>::clone(&m1::S); //~[no_short] absolute_paths
} }

View File

@ -0,0 +1,14 @@
error: consider bringing this path into scope with the `use` keyword
--> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:15:13
|
LL | let _ = ::m1::m2::X;
| ^^^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:6:9
|
LL | #![deny(clippy::absolute_paths)]
| ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -0,0 +1,16 @@
//@revisions: default allow_crates
//@[default]rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/default
//@[allow_crates]rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_crates
//@edition:2015
#![deny(clippy::absolute_paths)]
mod m1 {
pub mod m2 {
pub struct X;
}
}
fn main() {
let _ = ::m1::m2::X; //~[default] absolute_paths
}

View File

@ -1,2 +1 @@
absolute-paths-max-segments = 2 absolute-paths-allowed-crates = ["core", "crate"]
absolute-paths-allowed-crates = ["crate", "helper"]

View File

@ -0,0 +1 @@
absolute-paths-max-segments = 3

View File

@ -1,11 +0,0 @@
pub fn a() {}
pub mod b {
pub mod c {
pub mod d {
pub mod e {
pub fn f() {}
}
}
}
}

View File

@ -1 +0,0 @@
absolute-paths-max-segments = 2

View File

@ -0,0 +1 @@
absolute-paths-max-segments = 0