Auto merge of #130572 - matthiaskrgr:rollup-0q3qyg9, r=matthiaskrgr

Rollup of 5 pull requests

Successful merges:

 - #128001 (Improve documentation for <integer>::from_str_radix)
 - #130553 ([Clippy] Get rid of most `std` `match_def_path` usage, swap to diagnostic items.)
 - #130554 (`pal::unsupported::process::ExitCode`: use an `u8` instead of a `bool`)
 - #130556 (Mark the `link_cfg` feature as internal)
 - #130558 (Support 128-bit atomics on s390x)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-09-19 18:40:30 +00:00
commit 506f22b466
49 changed files with 265 additions and 199 deletions

View File

@ -204,7 +204,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Changes `impl Trait` to capture all lifetimes in scope.
(unstable, lifetime_capture_rules_2024, "1.76.0", None),
/// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
(unstable, link_cfg, "1.14.0", None),
(internal, link_cfg, "1.14.0", None),
/// Allows using `?Trait` trait bounds in more contexts.
(internal, more_maybe_bounds, "1.82.0", None),
/// Allows the `multiple_supertrait_upcastable` lint.

View File

@ -342,6 +342,7 @@
Upvars,
Vec,
VecDeque,
Waker,
Wrapper,
Wrapping,
Yield,
@ -501,6 +502,7 @@
black_box,
block,
bool,
bool_then,
borrowck_graphviz_format,
borrowck_graphviz_postflow,
box_new,
@ -512,6 +514,8 @@
breakpoint,
bridge,
bswap,
btreemap_contains_key,
btreemap_insert,
btreeset_iter,
builtin_syntax,
c,
@ -680,6 +684,7 @@
crt_dash_static: "crt-static",
csky_target_feature,
cstr_type,
cstring_as_c_str,
cstring_type,
ctlz,
ctlz_nonzero,
@ -835,6 +840,7 @@
f16_nan,
f16c_target_feature,
f32,
f32_epsilon,
f32_legacy_const_digits,
f32_legacy_const_epsilon,
f32_legacy_const_infinity,
@ -851,6 +857,7 @@
f32_legacy_const_radix,
f32_nan,
f64,
f64_epsilon,
f64_legacy_const_digits,
f64_legacy_const_epsilon,
f64_legacy_const_infinity,
@ -888,6 +895,7 @@
field,
field_init_shorthand,
file,
file_options,
float,
float_to_int_unchecked,
floorf128,
@ -973,7 +981,17 @@
half_open_range_patterns,
half_open_range_patterns_in_slices,
hash,
hashmap_contains_key,
hashmap_drain_ty,
hashmap_insert,
hashmap_iter_mut_ty,
hashmap_iter_ty,
hashmap_keys_ty,
hashmap_values_mut_ty,
hashmap_values_ty,
hashset_drain_ty,
hashset_iter,
hashset_iter_ty,
hexagon_target_feature,
hidden,
homogeneous_aggregate,
@ -1052,6 +1070,7 @@
inline_const,
inline_const_pat,
inout,
instant_now,
instruction_set,
integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
integral,
@ -1352,6 +1371,7 @@
on,
on_unimplemented,
opaque,
open_options_new,
ops,
opt_out_copy,
optimize,
@ -1359,10 +1379,14 @@
optin_builtin_traits,
option,
option_env,
option_expect,
option_unwrap,
options,
or,
or_patterns,
ord_cmp_method,
os_str_to_os_string,
os_string_as_os_str,
other,
out,
overflow_checks,
@ -1416,10 +1440,14 @@
pat_param,
patchable_function_entry,
path,
path_main_separator,
path_to_pathbuf,
pathbuf_as_path,
pattern_complexity,
pattern_parentheses,
pattern_type,
pattern_types,
permissions_from_mode,
phantom_data,
pic,
pie,
@ -1571,6 +1599,7 @@
residual,
result,
result_ffi_guarantees,
result_ok_method,
resume,
return_position_impl_trait_in_trait,
return_type_notation,
@ -1823,6 +1852,7 @@
slice,
slice_from_raw_parts,
slice_from_raw_parts_mut,
slice_into_vec,
slice_iter,
slice_len_fn,
slice_patterns,
@ -1857,16 +1887,25 @@
store,
str,
str_chars,
str_ends_with,
str_from_utf8,
str_from_utf8_mut,
str_from_utf8_unchecked,
str_from_utf8_unchecked_mut,
str_len,
str_split_whitespace,
str_starts_with,
str_trim,
str_trim_end,
str_trim_start,
strict_provenance,
string_as_mut_str,
string_as_str,
string_deref_patterns,
string_from_utf8,
string_insert_str,
string_new,
string_push_str,
stringify,
struct_field_attributes,
struct_inherit,
@ -2071,7 +2110,14 @@
var,
variant_count,
vec,
vec_as_mut_slice,
vec_as_slice,
vec_from_elem,
vec_is_empty,
vec_macro,
vec_new,
vec_pop,
vec_with_capacity,
vecdeque_iter,
version,
vfp2,

View File

@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
// ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
// also strip v128 from the data_layout below to match the older LLVM's expectation.
base.features = "-vector".into();
base.max_atomic_width = Some(64);
base.max_atomic_width = Some(128);
base.min_global_align = Some(16);
base.stack_probes = StackProbeType::Inline;
base.supported_sanitizers =

View File

@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
// ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
// also strip v128 from the data_layout below to match the older LLVM's expectation.
base.features = "-vector".into();
base.max_atomic_width = Some(64);
base.max_atomic_width = Some(128);
base.min_global_align = Some(16);
base.static_position_independent_executables = true;
base.stack_probes = StackProbeType::Inline;

View File

@ -916,6 +916,7 @@ pub fn pop_last(&mut self) -> Option<(K, V)>
/// assert_eq!(map.contains_key(&2), false);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "btreemap_contains_key")]
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
K: Borrow<Q> + Ord,
@ -981,6 +982,7 @@ pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V>
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_confusables("push", "put", "set")]
#[cfg_attr(not(test), rustc_diagnostic_item = "btreemap_insert")]
pub fn insert(&mut self, key: K, value: V) -> Option<V>
where
K: Ord,

View File

@ -576,6 +576,7 @@ pub fn as_bytes_with_nul(&self) -> &[u8] {
#[inline]
#[must_use]
#[stable(feature = "as_c_str", since = "1.20.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_as_c_str")]
pub fn as_c_str(&self) -> &CStr {
&*self
}

View File

@ -496,6 +496,7 @@ pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A>
#[rustc_allow_incoherent_impl]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
#[cfg_attr(not(test), rustc_diagnostic_item = "slice_into_vec")]
pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
// N.B., see the `hack` module in this file for more details.
hack::into_vec(self)

View File

@ -440,6 +440,7 @@ impl String {
/// ```
#[inline]
#[rustc_const_stable(feature = "const_string_new", since = "1.39.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "string_new")]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
pub const fn new() -> String {
@ -571,6 +572,7 @@ pub fn from_str(_: &str) -> String {
/// [`into_bytes`]: String::into_bytes
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "string_from_utf8")]
pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
match str::from_utf8(&vec) {
Ok(..) => Ok(String { vec }),
@ -1073,6 +1075,7 @@ pub fn into_bytes(self) -> Vec<u8> {
#[inline]
#[must_use]
#[stable(feature = "string_as_str", since = "1.7.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "string_as_str")]
pub fn as_str(&self) -> &str {
self
}
@ -1092,6 +1095,7 @@ pub fn as_str(&self) -> &str {
#[inline]
#[must_use]
#[stable(feature = "string_as_str", since = "1.7.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "string_as_mut_str")]
pub fn as_mut_str(&mut self) -> &mut str {
self
}
@ -1111,6 +1115,7 @@ pub fn as_mut_str(&mut self) -> &mut str {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_confusables("append", "push")]
#[cfg_attr(not(test), rustc_diagnostic_item = "string_push_str")]
pub fn push_str(&mut self, string: &str) {
self.vec.extend_from_slice(string.as_bytes())
}
@ -1745,6 +1750,7 @@ unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
#[cfg(not(no_global_oom_handling))]
#[inline]
#[stable(feature = "insert_str", since = "1.16.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "string_insert_str")]
pub fn insert_str(&mut self, idx: usize, string: &str) {
assert!(self.is_char_boundary(idx));

View File

@ -416,6 +416,7 @@ impl<T> Vec<T> {
/// ```
#[inline]
#[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "vec_new")]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
pub const fn new() -> Self {
@ -476,6 +477,7 @@ pub const fn new() -> Self {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[cfg_attr(not(test), rustc_diagnostic_item = "vec_with_capacity")]
pub fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_in(capacity, Global)
}
@ -1545,6 +1547,7 @@ pub fn truncate(&mut self, len: usize) {
/// ```
#[inline]
#[stable(feature = "vec_as_slice", since = "1.7.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_slice")]
pub fn as_slice(&self) -> &[T] {
self
}
@ -1562,6 +1565,7 @@ pub fn as_slice(&self) -> &[T] {
/// ```
#[inline]
#[stable(feature = "vec_as_slice", since = "1.7.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_mut_slice")]
pub fn as_mut_slice(&mut self) -> &mut [T] {
self
}
@ -2380,6 +2384,7 @@ pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> {
/// Takes *O*(1) time.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "vec_pop")]
pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
None
@ -2573,6 +2578,7 @@ pub fn len(&self) -> usize {
/// assert!(!v.is_empty());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "vec_is_empty")]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
@ -3044,6 +3050,7 @@ pub fn dedup(&mut self) {
#[doc(hidden)]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "vec_from_elem")]
pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
<T as SpecFromElem>::from_elem(elem, n, Global)
}

View File

@ -55,6 +55,7 @@ pub fn then_some<T>(self, t: T) -> Option<T> {
/// assert_eq!(a, 1);
/// ```
#[stable(feature = "lazy_bool_to_option", since = "1.50.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "bool_then")]
#[inline]
pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
if self { Some(f()) } else { None }

View File

@ -415,6 +415,7 @@ impl f32 {
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
/// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "f32_epsilon")]
pub const EPSILON: f32 = 1.19209290e-07_f32;
/// Smallest finite `f32` value.

View File

@ -414,6 +414,7 @@ impl f64 {
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
/// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "f64_epsilon")]
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
/// Smallest finite `f64` value.

View File

@ -23,6 +23,16 @@ macro_rules! unlikely {
};
}
// Use this when the generated code should differ between signed and unsigned types.
macro_rules! sign_dependent_expr {
(signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
$signed_case
};
(unsigned ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
$unsigned_case
};
}
// All these modules are technically private and only exposed for coretests:
#[cfg(not(no_fp_fmt_parse))]
pub mod bignum;
@ -1410,15 +1420,25 @@ const fn from_str_radix_panic(radix: u32) {
}
macro_rules! from_str_radix {
($($int_ty:ty)+) => {$(
($signedness:ident $($int_ty:ty)+) => {$(
impl $int_ty {
/// Converts a string slice in a given base to an integer.
///
/// The string is expected to be an optional `+` sign
/// followed by digits.
/// Leading and trailing whitespace represent an error.
/// Digits are a subset of these characters, depending on `radix`:
/// The string is expected to be an optional
#[doc = sign_dependent_expr!{
$signedness ?
if signed {
" `+` or `-` "
}
if unsigned {
" `+` "
}
}]
/// sign followed by only digits. Leading and trailing non-digit characters (including
/// whitespace) represent an error. Underscores (which are accepted in rust literals)
/// also represent an error.
///
/// Digits are a subset of these characters, depending on `radix`:
/// * `0-9`
/// * `a-z`
/// * `A-Z`
@ -1430,10 +1450,13 @@ impl $int_ty {
/// # Examples
///
/// Basic usage:
///
/// ```
#[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_str_radix(\"A\", 16), Ok(10));")]
/// ```
/// Trailing space returns error:
/// ```
#[doc = concat!("assert!(", stringify!($int_ty), "::from_str_radix(\"1 \", 10).is_err());")]
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
pub const fn from_str_radix(src: &str, radix: u32) -> Result<$int_ty, ParseIntError> {
@ -1535,20 +1558,31 @@ macro_rules! run_checked_loop {
)+}
}
from_str_radix! { i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 }
from_str_radix! { unsigned u8 u16 u32 u64 u128 }
from_str_radix! { signed i8 i16 i32 i64 i128 }
// Re-use the relevant implementation of from_str_radix for isize and usize to avoid outputting two
// identical functions.
macro_rules! from_str_radix_size_impl {
($($t:ident $size:ty),*) => {$(
($($signedness:ident $t:ident $size:ty),*) => {$(
impl $size {
/// Converts a string slice in a given base to an integer.
///
/// The string is expected to be an optional `+` sign
/// followed by digits.
/// Leading and trailing whitespace represent an error.
/// Digits are a subset of these characters, depending on `radix`:
/// The string is expected to be an optional
#[doc = sign_dependent_expr!{
$signedness ?
if signed {
" `+` or `-` "
}
if unsigned {
" `+` "
}
}]
/// sign followed by only digits. Leading and trailing non-digit characters (including
/// whitespace) represent an error. Underscores (which are accepted in rust literals)
/// also represent an error.
///
/// Digits are a subset of these characters, depending on `radix`:
/// * `0-9`
/// * `a-z`
/// * `A-Z`
@ -1560,10 +1594,13 @@ impl $size {
/// # Examples
///
/// Basic usage:
///
/// ```
#[doc = concat!("assert_eq!(", stringify!($size), "::from_str_radix(\"A\", 16), Ok(10));")]
/// ```
/// Trailing space returns error:
/// ```
#[doc = concat!("assert!(", stringify!($size), "::from_str_radix(\"1 \", 10).is_err());")]
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
pub const fn from_str_radix(src: &str, radix: u32) -> Result<$size, ParseIntError> {
@ -1576,8 +1613,8 @@ pub const fn from_str_radix(src: &str, radix: u32) -> Result<$size, ParseIntErro
}
#[cfg(target_pointer_width = "16")]
from_str_radix_size_impl! { i16 isize, u16 usize }
from_str_radix_size_impl! { signed i16 isize, unsigned u16 usize }
#[cfg(target_pointer_width = "32")]
from_str_radix_size_impl! { i32 isize, u32 usize }
from_str_radix_size_impl! { signed i32 isize, unsigned u32 usize }
#[cfg(target_pointer_width = "64")]
from_str_radix_size_impl! { i64 isize, u64 usize }
from_str_radix_size_impl! { signed i64 isize, unsigned u64 usize }

View File

@ -1972,16 +1972,6 @@ pub const fn wrapping_neg(self) -> Self {
};
}
// Use this when the generated code should differ between signed and unsigned types.
macro_rules! sign_dependent_expr {
(signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
$signed_case
};
(unsigned ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
$unsigned_case
};
}
nonzero_integer! {
Self = NonZeroU8,
Primitive = unsigned u8,

View File

@ -923,6 +923,7 @@ pub const fn as_mut_slice(&mut self) -> &mut [T] {
#[inline]
#[track_caller]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "option_expect")]
#[rustc_const_unstable(feature = "const_option", issue = "67441")]
pub const fn expect(self, msg: &str) -> T {
match self {
@ -960,6 +961,7 @@ pub const fn expect(self, msg: &str) -> T {
#[inline(always)]
#[track_caller]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "option_unwrap")]
#[rustc_const_unstable(feature = "const_option", issue = "67441")]
pub const fn unwrap(self) -> T {
match self {

View File

@ -653,6 +653,7 @@ pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "result_ok_method")]
pub fn ok(self) -> Option<T> {
match self {
Ok(x) => Some(x),

View File

@ -134,6 +134,7 @@ impl str {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_str_len", since = "1.39.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "str_len")]
#[must_use]
#[inline]
pub const fn len(&self) -> usize {
@ -1157,6 +1158,7 @@ pub fn contains<P: Pattern>(&self, pat: P) -> bool {
/// assert!(bananas.starts_with(&['a', 'b', 'c', 'd']));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "str_starts_with")]
pub fn starts_with<P: Pattern>(&self, pat: P) -> bool {
pat.is_prefix_of(self)
}
@ -1181,6 +1183,7 @@ pub fn starts_with<P: Pattern>(&self, pat: P) -> bool {
/// assert!(!bananas.ends_with("nana"));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "str_ends_with")]
pub fn ends_with<P: Pattern>(&self, pat: P) -> bool
where
for<'a> P::Searcher<'a>: ReverseSearcher<'a>,

View File

@ -414,6 +414,7 @@ pub const fn build(self) -> Context<'a> {
/// [`Wake`]: ../../alloc/task/trait.Wake.html
#[repr(transparent)]
#[stable(feature = "futures_api", since = "1.36.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "Waker")]
pub struct Waker {
waker: RawWaker,
}

View File

@ -244,6 +244,8 @@ fn test_from_str_radix() {
assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
assert_eq!($T::from_str_radix("10_0", 10).ok(), None::<$T>);
assert_eq!(u32::from_str_radix("-9", 10).ok(), None::<u32>);
}
#[test]

View File

@ -1037,6 +1037,7 @@ pub unsafe fn get_many_unchecked_mut<Q: ?Sized, const N: usize>(
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_contains_key")]
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
where
K: Borrow<Q>,
@ -1100,6 +1101,7 @@ pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_confusables("push", "append", "put")]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_insert")]
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
self.base.insert(k, v)
}
@ -1391,6 +1393,7 @@ fn index(&self, key: &Q) -> &V {
/// let iter = map.iter();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_iter_ty")]
pub struct Iter<'a, K: 'a, V: 'a> {
base: base::Iter<'a, K, V>,
}
@ -1429,6 +1432,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// let iter = map.iter_mut();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_iter_mut_ty")]
pub struct IterMut<'a, K: 'a, V: 'a> {
base: base::IterMut<'a, K, V>,
}
@ -1489,6 +1493,7 @@ pub(super) fn iter(&self) -> Iter<'_, K, V> {
/// let iter_keys = map.keys();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_keys_ty")]
pub struct Keys<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
@ -1527,6 +1532,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// let iter_values = map.values();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_values_ty")]
pub struct Values<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
@ -1565,6 +1571,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// let iter = map.drain();
/// ```
#[stable(feature = "drain", since = "1.6.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_drain_ty")]
pub struct Drain<'a, K: 'a, V: 'a> {
base: base::Drain<'a, K, V>,
}
@ -1622,6 +1629,7 @@ pub struct ExtractIf<'a, K, V, F>
/// let iter_values = map.values_mut();
/// ```
#[stable(feature = "map_values_mut", since = "1.10.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_values_mut_ty")]
pub struct ValuesMut<'a, K: 'a, V: 'a> {
inner: IterMut<'a, K, V>,
}

View File

@ -1271,6 +1271,7 @@ fn sub(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
/// let mut iter = a.iter();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashset_iter_ty")]
pub struct Iter<'a, K: 'a> {
base: base::Iter<'a, K>,
}
@ -1313,6 +1314,7 @@ pub struct IntoIter<K> {
/// let mut drain = a.drain();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "hashset_drain_ty")]
pub struct Drain<'a, K: 'a> {
base: base::Drain<'a, K>,
}

View File

@ -196,6 +196,7 @@ pub unsafe fn from_encoded_bytes_unchecked(bytes: Vec<u8>) -> Self {
/// let os_str = OsStr::new("foo");
/// assert_eq!(os_string.as_os_str(), os_str);
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "os_string_as_os_str")]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[inline]
@ -918,6 +919,7 @@ pub fn to_string_lossy(&self) -> Cow<'_, str> {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[cfg_attr(not(test), rustc_diagnostic_item = "os_str_to_os_string")]
pub fn to_os_string(&self) -> OsString {
OsString { inner: self.inner.to_owned() }
}

View File

@ -466,6 +466,7 @@ pub fn create_new<P: AsRef<Path>>(path: P) -> io::Result<File> {
/// ```
#[must_use]
#[stable(feature = "with_options", since = "1.58.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "file_options")]
pub fn options() -> OpenOptions {
OpenOptions::new()
}
@ -1009,6 +1010,7 @@ impl OpenOptions {
/// let mut options = OpenOptions::new();
/// let file = options.read(true).open("foo.txt");
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "open_options_new")]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
pub fn new() -> Self {

View File

@ -334,6 +334,7 @@ pub trait PermissionsExt {
/// assert_eq!(permissions.mode(), 0o644);
/// ```
#[stable(feature = "fs_ext", since = "1.1.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "permissions_from_mode")]
fn from_mode(mode: u32) -> Self;
}

View File

@ -263,6 +263,7 @@ pub fn is_separator(c: char) -> bool {
///
/// For example, `/` on Unix and `\` on Windows.
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "path_main_separator")]
pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
/// The primary separator of path components for the current platform.
@ -1226,6 +1227,7 @@ pub fn with_capacity(capacity: usize) -> PathBuf {
/// let p = PathBuf::from("/test");
/// assert_eq!(Path::new("/test"), p.as_path());
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "pathbuf_as_path")]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[inline]
@ -2264,6 +2266,7 @@ pub fn to_string_lossy(&self) -> Cow<'_, str> {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "path_to_pathbuf")]
pub fn to_path_buf(&self) -> PathBuf {
PathBuf::from(self.inner.to_os_string())
}

View File

@ -255,11 +255,11 @@ pub fn code(self) -> Option<NonZero<i32>> {
}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct ExitCode(bool);
pub struct ExitCode(u8);
impl ExitCode {
pub const SUCCESS: ExitCode = ExitCode(false);
pub const FAILURE: ExitCode = ExitCode(true);
pub const SUCCESS: ExitCode = ExitCode(0);
pub const FAILURE: ExitCode = ExitCode(1);
pub fn as_i32(&self) -> i32 {
self.0 as i32
@ -268,10 +268,7 @@ pub fn as_i32(&self) -> i32 {
impl From<u8> for ExitCode {
fn from(code: u8) -> Self {
match code {
0 => Self::SUCCESS,
1..=255 => Self::FAILURE,
}
Self(code)
}
}

View File

@ -280,6 +280,7 @@ impl Instant {
/// ```
#[must_use]
#[stable(feature = "time2", since = "1.8.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "instant_now")]
pub fn now() -> Instant {
Instant(time::Instant::now())
}

View File

@ -1,8 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context};
use clippy_utils::{
can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified, match_def_path,
paths, peel_hir_expr_while, SpanlessEq,
can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified,
peel_hir_expr_while, SpanlessEq,
};
use core::fmt::{self, Write};
use rustc_errors::Applicability;
@ -11,7 +11,7 @@
use rustc_hir::{Block, Expr, ExprKind, HirId, Pat, Stmt, StmtKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::{Span, SyntaxContext, DUMMY_SP};
use rustc_span::{sym, Span, SyntaxContext, DUMMY_SP};
declare_clippy_lint! {
/// ### What it does
@ -269,9 +269,9 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio
key,
call_ctxt: expr.span.ctxt(),
};
if match_def_path(cx, id, &paths::BTREEMAP_CONTAINS_KEY) {
if cx.tcx.is_diagnostic_item(sym::btreemap_contains_key, id) {
Some((MapType::BTree, expr))
} else if match_def_path(cx, id, &paths::HASHMAP_CONTAINS_KEY) {
} else if cx.tcx.is_diagnostic_item(sym::hashmap_contains_key, id) {
Some((MapType::Hash, expr))
} else {
None
@ -306,7 +306,7 @@ struct InsertExpr<'tcx> {
fn try_parse_insert<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<InsertExpr<'tcx>> {
if let ExprKind::MethodCall(_, map, [key, value], _) = expr.kind {
let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
if match_def_path(cx, id, &paths::BTREEMAP_INSERT) || match_def_path(cx, id, &paths::HASHMAP_INSERT) {
if cx.tcx.is_diagnostic_item(sym::btreemap_insert, id) || cx.tcx.is_diagnostic_item(sym::hashmap_insert, id) {
Some(InsertExpr { map, key, value })
} else {
None

View File

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{higher, match_def_path, paths};
use clippy_utils::higher;
use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
@ -70,7 +70,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let arg = match expr.kind {
ExprKind::MethodCall(_, _, [arg], _) => {
if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& match_def_path(cx, fn_def_id, &paths::PUSH_STR)
&& cx.tcx.is_diagnostic_item(sym::string_push_str, fn_def_id)
{
arg
} else {

View File

@ -112,7 +112,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
fn is_instant_now_call(cx: &LateContext<'_>, expr_block: &'_ Expr<'_>) -> bool {
if let ExprKind::Call(fn_expr, []) = expr_block.kind
&& let Some(fn_id) = clippy_utils::path_def_id(cx, fn_expr)
&& clippy_utils::match_def_path(cx, fn_id, &clippy_utils::paths::INSTANT_NOW)
&& cx.tcx.is_diagnostic_item(sym::instant_now, fn_id)
{
true
} else {

View File

@ -1,10 +1,5 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::higher::ForLoop;
use clippy_utils::match_any_def_paths;
use clippy_utils::paths::{
HASHMAP_DRAIN, HASHMAP_ITER, HASHMAP_ITER_MUT, HASHMAP_KEYS, HASHMAP_VALUES, HASHMAP_VALUES_MUT, HASHSET_DRAIN,
HASHSET_ITER_TY,
};
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
@ -44,28 +39,23 @@
impl LateLintPass<'_> for IterOverHashType {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>) {
let hash_iter_tys = [
sym::HashMap,
sym::HashSet,
sym::hashmap_keys_ty,
sym::hashmap_values_ty,
sym::hashmap_values_mut_ty,
sym::hashmap_iter_ty,
sym::hashmap_iter_mut_ty,
sym::hashmap_drain_ty,
sym::hashset_iter_ty,
sym::hashset_drain_ty,
];
if let Some(for_loop) = ForLoop::hir(expr)
&& !for_loop.body.span.from_expansion()
&& let ty = cx.typeck_results().expr_ty(for_loop.arg).peel_refs()
&& let Some(adt) = ty.ty_adt_def()
&& let did = adt.did()
&& (match_any_def_paths(
cx,
did,
&[
&HASHMAP_KEYS,
&HASHMAP_VALUES,
&HASHMAP_VALUES_MUT,
&HASHMAP_ITER,
&HASHMAP_ITER_MUT,
&HASHMAP_DRAIN,
&HASHSET_ITER_TY,
&HASHSET_DRAIN,
],
)
.is_some()
|| is_type_diagnostic_item(cx, ty, sym::HashMap)
|| is_type_diagnostic_item(cx, ty, sym::HashSet))
&& hash_iter_tys.into_iter().any(|sym| is_type_diagnostic_item(cx, ty, sym))
{
span_lint(
cx,

View File

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_diag_item_method, is_trait_method, match_def_path, path_to_local_id, paths};
use clippy_utils::{is_diag_item_method, is_trait_method, path_to_local_id};
use rustc_errors::Applicability;
use rustc_hir::{Body, Closure, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@ -96,7 +96,7 @@ fn should_lint(cx: &LateContext<'_>, args: &[Expr<'_>], method_str: &str) -> boo
ExprKind::Path(qpath) => cx
.qpath_res(qpath, fm_arg.hir_id)
.opt_def_id()
.is_some_and(|did| match_def_path(cx, did, &paths::CORE_RESULT_OK_METHOD)),
.is_some_and(|did| cx.tcx.is_diagnostic_item(sym::result_ok_method, did)),
// Detect `|x| x.ok()`
ExprKind::Closure(Closure { body, .. }) => {
if let Body {

View File

@ -1,10 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::{match_def_path, paths, SpanlessEq};
use clippy_utils::SpanlessEq;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Pat, Stmt, StmtKind, UnOp};
use rustc_lint::LateContext;
use rustc_span::Span;
use rustc_span::{sym, Symbol, Span};
use std::borrow::Cow;
use super::MANUAL_WHILE_LET_SOME;
@ -47,20 +47,20 @@ fn report_lint(cx: &LateContext<'_>, pop_span: Span, pop_stmt_kind: PopStmt<'_>,
);
}
fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: &[&str]) -> bool {
fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: Symbol) -> bool {
if let ExprKind::MethodCall(..) = expr.kind
&& let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
{
match_def_path(cx, id, method)
cx.tcx.is_diagnostic_item(method, id)
} else {
false
}
}
fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr<'_>) -> bool {
if (match_method_call(cx, expr, &paths::OPTION_UNWRAP) || match_method_call(cx, expr, &paths::OPTION_EXPECT))
if (match_method_call(cx, expr, sym::option_unwrap) || match_method_call(cx, expr, sym::option_expect))
&& let ExprKind::MethodCall(_, unwrap_recv, ..) = expr.kind
&& match_method_call(cx, unwrap_recv, &paths::VEC_POP)
&& match_method_call(cx, unwrap_recv, sym::vec_pop)
&& let ExprKind::MethodCall(_, pop_recv, ..) = unwrap_recv.kind
{
// make sure they're the same `Vec`
@ -96,7 +96,7 @@ fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &E
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, full_cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>, loop_span: Span) {
if let ExprKind::Unary(UnOp::Not, cond) = full_cond.kind
&& let ExprKind::MethodCall(_, is_empty_recv, _, _) = cond.kind
&& match_method_call(cx, cond, &paths::VEC_IS_EMPTY)
&& match_method_call(cx, cond, sym::vec_is_empty)
&& let ExprKind::Block(body, _) = body.kind
&& let Some(stmt) = body.stmts.first()
{

View File

@ -1,7 +1,7 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{is_trait_method, match_def_path, paths, peel_hir_expr_refs};
use clippy_utils::{is_trait_method, peel_hir_expr_refs};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Expr, ExprKind, Mutability, QPath};
@ -56,7 +56,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
&& let Res::Def(DefKind::Const, receiver_def_id) = path.res
&& is_trait_method(cx, target, sym::ToString)
&& self.msrv.meets(msrvs::PATH_MAIN_SEPARATOR_STR)
&& match_def_path(cx, receiver_def_id, &paths::PATH_MAIN_SEPARATOR)
&& cx.tcx.is_diagnostic_item(sym::path_main_separator, receiver_def_id)
&& let ty::Ref(_, ty, Mutability::Not) = cx.typeck_results().expr_ty_adjusted(expr).kind()
&& ty.is_str()
{

View File

@ -4,7 +4,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::usage::mutated_variables;
use clippy_utils::{eq_expr_value, higher, match_def_path, paths};
use clippy_utils::{eq_expr_value, higher};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
@ -14,7 +14,7 @@
use rustc_middle::ty;
use rustc_session::impl_lint_pass;
use rustc_span::source_map::Spanned;
use rustc_span::Span;
use rustc_span::{sym, Span};
use std::iter;
declare_clippy_lint! {
@ -76,9 +76,9 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
&& self.msrv.meets(msrvs::STR_STRIP_PREFIX)
&& let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id)
{
let strip_kind = if match_def_path(cx, method_def_id, &paths::STR_STARTS_WITH) {
let strip_kind = if cx.tcx.is_diagnostic_item(sym::str_starts_with, method_def_id) {
StripKind::Prefix
} else if match_def_path(cx, method_def_id, &paths::STR_ENDS_WITH) {
} else if cx.tcx.is_diagnostic_item(sym::str_ends_with, method_def_id) {
StripKind::Suffix
} else {
return;
@ -137,7 +137,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
if let ExprKind::MethodCall(_, arg, [], _) = expr.kind
&& let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& match_def_path(cx, method_def_id, &paths::STR_LEN)
&& cx.tcx.is_diagnostic_item(sym::str_len, method_def_id)
{
Some(arg)
} else {

View File

@ -1,9 +1,8 @@
use super::FILTER_MAP_BOOL_THEN;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::paths::BOOL_THEN;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::is_copy;
use clippy_utils::{is_from_proc_macro, is_trait_method, match_def_path, peel_blocks};
use clippy_utils::{is_from_proc_macro, is_trait_method, peel_blocks};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LintContext};
@ -35,7 +34,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &
&& let ExprKind::Closure(then_closure) = then_arg.kind
&& let then_body = peel_blocks(cx.tcx.hir().body(then_closure.body).value)
&& let Some(def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id)
&& match_def_path(cx, def_id, &BOOL_THEN)
&& cx.tcx.is_diagnostic_item(sym::bool_then, def_id)
&& !is_from_proc_macro(cx, expr)
// Count the number of derefs needed to get to the bool because we need those in the suggestion
&& let needed_derefs = cx.typeck_results().expr_adjustments(recv)

View File

@ -126,17 +126,18 @@ fn get_open_options(
&& let ExprKind::Path(path) = callee.kind
&& let Some(did) = cx.qpath_res(&path, callee.hir_id).opt_def_id()
{
match_any_def_paths(
cx,
did,
&[
&paths::TOKIO_IO_OPEN_OPTIONS_NEW,
&paths::OPEN_OPTIONS_NEW,
&paths::FILE_OPTIONS,
&paths::TOKIO_FILE_OPTIONS,
],
)
.is_some()
let std_file_options = [
sym::file_options,
sym::open_options_new,
];
let tokio_file_options: &[&[&str]] = &[
&paths::TOKIO_IO_OPEN_OPTIONS_NEW,
&paths::TOKIO_FILE_OPTIONS,
];
let is_std_options = std_file_options.into_iter().any(|sym| cx.tcx.is_diagnostic_item(sym, did));
is_std_options || match_any_def_paths(cx, did, tokio_file_options).is_some()
} else {
false
}

View File

@ -2,12 +2,12 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{match_def_path, path_to_local_id, paths, peel_blocks};
use clippy_utils::{path_to_local_id, peel_blocks};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::sym;
use rustc_span::{sym, Symbol};
use super::OPTION_AS_REF_DEREF;
@ -31,14 +31,14 @@ pub(super) fn check(
return;
}
let deref_aliases: [&[&str]; 7] = [
&paths::CSTRING_AS_C_STR,
&paths::OS_STRING_AS_OS_STR,
&paths::PATH_BUF_AS_PATH,
&paths::STRING_AS_STR,
&paths::STRING_AS_MUT_STR,
&paths::VEC_AS_SLICE,
&paths::VEC_AS_MUT_SLICE,
let deref_aliases: [Symbol; 7] = [
sym::cstring_as_c_str,
sym::os_string_as_os_str,
sym::pathbuf_as_path,
sym::string_as_str,
sym::string_as_mut_str,
sym::vec_as_slice,
sym::vec_as_mut_slice,
];
let is_deref = match map_arg.kind {
@ -48,7 +48,7 @@ pub(super) fn check(
.map_or(false, |fun_def_id| {
cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id)
|| cx.tcx.is_diagnostic_item(sym::deref_mut_method, fun_def_id)
|| deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
|| deref_aliases.iter().any(|&sym| cx.tcx.is_diagnostic_item(sym, fun_def_id))
})
},
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
@ -69,7 +69,7 @@ pub(super) fn check(
let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
cx.tcx.is_diagnostic_item(sym::deref_method, method_did)
|| cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did)
|| deref_aliases.iter().any(|path| match_def_path(cx, method_did, path))
|| deref_aliases.iter().any(|&sym| cx.tcx.is_diagnostic_item(sym, method_did))
} else {
false
}

View File

@ -1,13 +1,13 @@
use crate::methods::{single_char_insert_string, single_char_push_string};
use clippy_utils::{match_def_path, paths};
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::sym;
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
if match_def_path(cx, fn_def_id, &paths::PUSH_STR) {
if cx.tcx.is_diagnostic_item(sym::string_push_str, fn_def_id) {
single_char_push_string::check(cx, expr, receiver, args);
} else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) {
} else if cx.tcx.is_diagnostic_item(sym::string_insert_str, fn_def_id) {
single_char_insert_string::check(cx, expr, receiver, args);
}
}

View File

@ -6,7 +6,7 @@
use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::visitors::find_all_ret_expressions;
use clippy_utils::{
fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, match_def_path, paths, peel_middle_ty_refs,
fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, peel_middle_ty_refs,
return_ty,
};
use rustc_errors::Applicability;
@ -250,7 +250,7 @@ fn check_string_from_utf8<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>,
if let Some((call, arg)) = skip_addr_of_ancestors(cx, expr)
&& !arg.span.from_expansion()
&& let ExprKind::Call(callee, _) = call.kind
&& fn_def_id(cx, call).is_some_and(|did| match_def_path(cx, did, &paths::STRING_FROM_UTF8))
&& fn_def_id(cx, call).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::string_from_utf8, did))
&& let Some(unwrap_call) = get_parent_expr(cx, call)
&& let ExprKind::MethodCall(unwrap_method_name, ..) = unwrap_call.kind
&& matches!(unwrap_method_name.ident.name, sym::unwrap | sym::expect)

View File

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_trait_method, match_def_path, paths};
use clippy_utils::is_trait_method;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
@ -12,7 +12,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'
let ty = cx.typeck_results().expr_ty(recv);
if let Some(did) = ty.ty_adt_def()
&& match_def_path(cx, did.did(), &paths::WAKER)
&& cx.tcx.is_diagnostic_item(sym::Waker, did.did())
&& let ExprKind::MethodCall(_, waker_ref, &[], _) = recv.kind
&& is_trait_method(cx, recv, sym::Clone)
{

View File

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{snippet_with_applicability, SpanRangeExt};
use clippy_utils::{match_def_path, paths};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@ -63,7 +62,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
ExprKind::Call(func, [param]) => {
if let ExprKind::Path(ref path) = func.kind
&& let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
&& match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE)
&& cx.tcx.is_diagnostic_item(sym::permissions_from_mode, def_id)
&& let ExprKind::Lit(_) = param.kind
&& param.span.eq_ctxt(expr.span)
&& param

View File

@ -1,12 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{match_def_path, paths, sugg};
use clippy_utils::sugg;
use rustc_ast::util::parser::AssocOp;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::source_map::Spanned;
use rustc_span::{sym, source_map::Spanned};
use super::FLOAT_EQUALITY_WITHOUT_ABS;
@ -36,7 +36,7 @@ pub(crate) fn check<'tcx>(
// right hand side matches either f32::EPSILON or f64::EPSILON
&& let ExprKind::Path(ref epsilon_path) = rhs.kind
&& let Res::Def(DefKind::AssocConst, def_id) = cx.qpath_res(epsilon_path, rhs.hir_id)
&& (match_def_path(cx, def_id, &paths::F32_EPSILON) || match_def_path(cx, def_id, &paths::F64_EPSILON))
&& ([sym::f32_epsilon, sym::f64_epsilon].into_iter().any(|sym| cx.tcx.is_diagnostic_item(sym, def_id)))
// values of the subtractions on the left hand side are of the type float
&& let t_val_l = cx.typeck_results().expr_ty(val_l)

View File

@ -2,7 +2,7 @@
use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap};
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth};
use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
use clippy_utils::fn_has_unsatisfiable_preds;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{def_id, Body, FnDecl, LangItem};
@ -102,8 +102,8 @@ fn check_fn(
&& is_type_lang_item(cx, arg_ty, LangItem::String));
let from_deref = !from_borrow
&& (match_def_path(cx, fn_def_id, &paths::PATH_TO_PATH_BUF)
|| match_def_path(cx, fn_def_id, &paths::OS_STR_TO_OS_STRING));
&& (cx.tcx.is_diagnostic_item(sym::path_to_pathbuf, fn_def_id)
|| cx.tcx.is_diagnostic_item(sym::os_str_to_os_string, fn_def_id));
if !from_borrow && !from_deref {
continue;

View File

@ -3,7 +3,7 @@
use clippy_utils::higher::VecArgs;
use clippy_utils::macros::matching_root_macro_call;
use clippy_utils::source::snippet;
use clippy_utils::{expr_or_init, fn_def_id, match_def_path, paths};
use clippy_utils::{expr_or_init, fn_def_id};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@ -67,7 +67,7 @@ fn emit_lint(cx: &LateContext<'_>, span: Span, kind: &str, note: &'static str, s
fn check_vec_macro(cx: &LateContext<'_>, expr: &Expr<'_>) {
if matching_root_macro_call(cx, expr.span, sym::vec_macro).is_some()
&& let Some(VecArgs::Repeat(repeat_expr, len_expr)) = VecArgs::hir(cx, expr)
&& fn_def_id(cx, repeat_expr).is_some_and(|did| match_def_path(cx, did, &paths::VEC_WITH_CAPACITY))
&& fn_def_id(cx, repeat_expr).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::vec_with_capacity, did))
&& !len_expr.span.from_expansion()
&& let Some(Constant::Int(2..)) = ConstEvalCtxt::new(cx).eval(expr_or_init(cx, len_expr))
{
@ -91,7 +91,7 @@ fn check_repeat_fn(cx: &LateContext<'_>, expr: &Expr<'_>) {
if !expr.span.from_expansion()
&& fn_def_id(cx, expr).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::iter_repeat, did))
&& let ExprKind::Call(_, [repeat_expr]) = expr.kind
&& fn_def_id(cx, repeat_expr).is_some_and(|did| match_def_path(cx, did, &paths::VEC_WITH_CAPACITY))
&& fn_def_id(cx, repeat_expr).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::vec_with_capacity, did))
&& !repeat_expr.span.from_expansion()
{
emit_lint(

View File

@ -2,8 +2,8 @@
use clippy_utils::macros::matching_root_macro_call;
use clippy_utils::sugg::Sugg;
use clippy_utils::{
get_enclosing_block, is_expr_path_def_path, is_integer_literal, is_path_diagnostic_item, path_to_local,
path_to_local_id, paths, SpanlessEq,
get_enclosing_block, is_integer_literal, is_path_diagnostic_item, path_to_local,
path_to_local_id, SpanlessEq,
};
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
@ -150,10 +150,10 @@ fn as_vec_initializer<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Opt
}
if let ExprKind::Call(func, [len_expr]) = expr.kind
&& is_expr_path_def_path(cx, func, &paths::VEC_WITH_CAPACITY)
&& is_path_diagnostic_item(cx, func, sym::vec_with_capacity)
{
Some(InitializedSize::Initialized(len_expr))
} else if matches!(expr.kind, ExprKind::Call(func, _) if is_expr_path_def_path(cx, func, &paths::VEC_NEW)) {
} else if matches!(expr.kind, ExprKind::Call(func, _) if is_path_diagnostic_item(cx, func, sym::vec_new)) {
Some(InitializedSize::Uninitialized)
} else {
None

View File

@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{match_def_path, paths};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
@ -42,7 +41,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
&& let ty::Ref(_, inner_str, _) = cx.typeck_results().expr_ty_adjusted(expr).kind()
&& inner_str.is_str()
{
if match_def_path(cx, fun_def_id, &paths::STRING_NEW) {
if cx.tcx.is_diagnostic_item(sym::string_new, fun_def_id) {
span_lint_and_sugg(
cx,
UNNECESSARY_OWNED_EMPTY_STRINGS,

View File

@ -4,7 +4,7 @@
use crate::consts::{ConstEvalCtxt, Constant};
use crate::ty::is_type_diagnostic_item;
use crate::{is_expn_of, match_def_path, paths};
use crate::is_expn_of;
use rustc_ast::ast;
use rustc_hir as hir;
@ -297,10 +297,10 @@ pub fn hir(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<VecArgs<'a>> {
&& is_expn_of(fun.span, "vec").is_some()
&& let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
{
return if match_def_path(cx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 {
return if cx.tcx.is_diagnostic_item(sym::vec_from_elem, fun_def_id) && args.len() == 2 {
// `vec![elem; size]` case
Some(VecArgs::Repeat(&args[0], &args[1]))
} else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
} else if cx.tcx.is_diagnostic_item(sym::slice_into_vec, fun_def_id) && args.len() == 1 {
// `vec![a, b, c]` case
if let ExprKind::Call(_, [arg]) = &args[0].kind
&& let ExprKind::Array(args) = arg.kind
@ -309,7 +309,7 @@ pub fn hir(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<VecArgs<'a>> {
} else {
None
}
} else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() {
} else if cx.tcx.is_diagnostic_item(sym::vec_new, fun_def_id) && args.is_empty() {
Some(VecArgs::Vec(&[]))
} else {
None

View File

@ -4,6 +4,7 @@
//! Whenever possible, please consider diagnostic items over hardcoded paths.
//! See <https://github.com/rust-lang/rust-clippy/issues/5393> for more information.
// Paths inside rustc
pub const APPLICABILITY: [&str; 2] = ["rustc_lint_defs", "Applicability"];
pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
["rustc_lint_defs", "Applicability", "Unspecified"],
@ -12,50 +13,37 @@
["rustc_lint_defs", "Applicability", "MachineApplicable"],
];
pub const DIAG: [&str; 2] = ["rustc_errors", "Diag"];
pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"];
pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];
pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"];
pub const FILE_OPTIONS: [&str; 4] = ["std", "fs", "File", "options"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"];
pub const HASHMAP_CONTAINS_KEY: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "contains_key"];
pub const HASHMAP_INSERT: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "insert"];
pub const HASHMAP_ITER: [&str; 5] = ["std", "collections", "hash", "map", "Iter"];
pub const HASHMAP_ITER_MUT: [&str; 5] = ["std", "collections", "hash", "map", "IterMut"];
pub const HASHMAP_KEYS: [&str; 5] = ["std", "collections", "hash", "map", "Keys"];
pub const HASHMAP_VALUES: [&str; 5] = ["std", "collections", "hash", "map", "Values"];
pub const HASHMAP_DRAIN: [&str; 5] = ["std", "collections", "hash", "map", "Drain"];
pub const HASHMAP_VALUES_MUT: [&str; 5] = ["std", "collections", "hash", "map", "ValuesMut"];
pub const HASHSET_ITER_TY: [&str; 5] = ["std", "collections", "hash", "set", "Iter"];
pub const HASHSET_DRAIN: [&str; 5] = ["std", "collections", "hash", "set", "Drain"];
pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
pub const SYMBOL: [&str; 3] = ["rustc_span", "symbol", "Symbol"];
pub const SYMBOL_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Symbol", "as_str"];
pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"];
pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol", "to_ident_string"];
pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
// Paths in `core`/`alloc`/`std`. This should be avoided and cleaned up by adding diagnostic items.
pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
// Paths in clippy itself
pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];
pub const OPEN_OPTIONS_NEW: [&str; 4] = ["std", "fs", "OpenOptions", "new"];
pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
// Paths in external crates
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"];
pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
pub const PATH_MAIN_SEPARATOR: [&str; 3] = ["std", "path", "MAIN_SEPARATOR"];
pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
#[cfg_attr(not(unix), allow(clippy::invalid_paths))]
pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
pub const REGEX_BUILDER_NEW: [&str; 3] = ["regex", "RegexBuilder", "new"];
pub const REGEX_BYTES_BUILDER_NEW: [&str; 4] = ["regex", "bytes", "RegexBuilder", "new"];
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "bytes", "Regex", "new"];
@ -64,22 +52,6 @@
pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"];
pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl str>", "starts_with"];
pub const SYMBOL: [&str; 3] = ["rustc_span", "symbol", "Symbol"];
pub const SYMBOL_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Symbol", "as_str"];
pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"];
pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol", "to_ident_string"];
pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
pub const STRING_FROM_UTF8: [&str; 4] = ["alloc", "string", "String", "from_utf8"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const TOKIO_FILE_OPTIONS: [&str; 5] = ["tokio", "fs", "file", "File", "options"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
@ -90,15 +62,3 @@
pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "OpenOptions"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"];
pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"];
pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"];
pub const VEC_WITH_CAPACITY: [&str; 4] = ["alloc", "vec", "Vec", "with_capacity"];
pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"];
pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"];
pub const WAKER: [&str; 4] = ["core", "task", "wake", "Waker"];
pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"];
pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"];
pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"];